Angular UI 日历弹出框内容在拖放/调整大小/更改视图时消失

Angular UI Calendar popover content disappears on Drag / Drop / Resize / ChangeView

我是AngularJS的新手,我一直在尝试修改AngularUI Calendar but I ran into some issues while using Bootstrap Popovers来修改点击时的事件。

我希望默认视图为 agendaWeek,它工作正常,但是一旦我更改视图、调整大小或拖/放,弹出窗口内容就会消失,我不知道为什么。

但是,如果我在任何这些操作期间保持弹出窗口打开,它会在更改后显示弹出窗口的内容,但在关闭时会留下一个空的弹出窗口。

我不关心空弹出窗口,因为我可以将它们全部隐藏,但我希望弹出窗口在我执行任何操作时正确显示内容。我怎样才能做到这一点?

/*
 * myCalendar.js
 */

angular.module('ui.calendar', ['ui.calendar', 'ngAnimate', 'ui.bootstrap'])
  .controller('CalendarCtrl', function($scope, $compile, $timeout, uiCalendarConfig) {

    $scope.event = {
      id: 0,
      title: '',
      start: null,
      end: null,
      attribute1: '',
      attribute2: ''
    };


    $scope.events = [{
      id: 1,
      title: 'New Event 1',
      start: moment('2016-04-14 06:00', 'YYYY-MM-DD HH:mm'),
      end: moment('2016-04-14 08:00', 'YYYY-MM-DD HH:mm'),
      attribute1: 'Attr 1',
      attribute2: 'Attr 2',
      state: 'closed'
    }, {
      id: 2,
      title: 'New Event 2',
      start: moment('2016-04-14 02:00', 'YYYY-MM-DD HH:mm'),
      end: moment('2016-04-14 04:00', 'YYYY-MM-DD HH:mm'),
      attribute1: 'First attr',
      attribute2: 'Second attr',
      state: 'closed'
    }];

    $scope.hidePopover = {
      show: false
    };

    $scope.onEventRender = function(event, element) {
      element.popover({
        placement: 'right',
        html: true,
        trigger: 'manual',
        content: $('#popover'),
        container: 'body'
      });
      $scope.events[$scope.getEventIndex(event.id)].popoverElement = element;
    };

    $scope.onEventClick = function(event, jsEvent, view) {
      var index = $scope.getEventIndex(event.id);
      if ($scope.events[index].state == 'closed') {
        $scope.hidePopover.show = true;
        $scope.event = event;
        $scope.$apply();
        $scope.hideOtherPopups();
        $scope.events[index].popoverElement.popover('show');
        $scope.events[index].state = 'open';
        console.log("Event", event);
      } else {
        $scope.events[index].popoverElement.popover('hide');
        $scope.updatePopover(event);
        $scope.events[index].state = 'closed';
      }
    };

    $scope.getEventIndex = function(id) {
      var index = -1;
      for (var i = 0; i < $scope.events.length; i++) {
        if ($scope.events[i].id == id) {
          index = i;
        }
      }
      return index;
    };

    $scope.hideOtherPopups = function() {
      for (var i = 0; i < $scope.events.length; i++) {
        if ($scope.events[i].state == 'open') {
          $scope.events[i].state = 'closed';
          $scope.events[i].popoverElement.popover('hide');
          $scope.updatePopover($scope.event);
        }
      }
    };

    $scope.updatePopover = function(event) {
      $('#calendar').fullCalendar('updateEvent', event);
    };

    $scope.changeView = function(view, calendar) {
      $scope.hideOtherPopups();
      uiCalendarConfig.calendars[calendar].fullCalendar('changeView', view);
    };

    $scope.onEventDragStart = function(event, delta, revertFunc, jsEvent, ui, view) {
      $scope.hideOtherPopups();
    };

    $scope.onEventResizeStart = function() {
      $scope.hideOtherPopups();
    };

    $scope.renderCalender = function(calendar) {
      $timeout(function() {
        if (uiCalendarConfig.calendars[calendar]) {
          uiCalendarConfig.calendars[calendar].fullCalendar('render');
        }
      });
    };

    $scope.uiConfig = {
      calendar: {
        height: 1180,
        editable: true,
        header: {
          left: 'title',
          center: '',
          right: 'today prev,next'
        },
        defaultView: 'agendaWeek',
        eventRender: $scope.onEventRender,
        eventClick: $scope.onEventClick,
        eventDrop: $scope.onEventDrop,
        eventResizeStart: $scope.onEventResizeStart,
        eventDragStart: $scope.onEventDragStart
      }

};
    
$scope.eventSources = [$scope.events];

});
/*
 * custom.css
 */

body {
  margin-top: 200px;
}
hr {
  border-color: lightgray;
}
#leftDiv {
  float: left;
  border: 1px solid gray;
  width: 300px;
  height: 1140px;
  padding: 20px;
  text-align: center;
  background-color: #eeeeee;
}
#hiddenDiv {
  margin-top: 20px;
  height: 300px;
  border: 1px solid darkgray;
}
#rightDiv {
  float: left;
  border: 1px solid darkgray;
}
<!--index.html-->

<!DOCTYPE html>
<html lang="en" ng-app="ui.calendar" id="top">

<head>
  <title>Calendar</title>
  <link rel="stylesheet" href="http://angular-ui.github.io/ui-calendar/bower_components/bootstrap-css/css/bootstrap.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.6.1/fullcalendar.css" />
  <link rel="stylesheet" href="custom.css" />

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-animate.js"></script>
  <script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.3.1.js"></script>
  <script src="https://angular-ui.github.io/ui-calendar/bower_components/moment/moment.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.6.1/fullcalendar.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/2.6.1/gcal.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-calendar/1.0.0/calendar.js"></script>-->
  <script src="myCalendar.js"></script>
</head>

<body data-spy="scroll">
  <header class="navbar navbar-inverse navbar-fixed-top">
    <div class="navbar-inner">
      <div class="container">

      </div>
    </div>
  </header>
  <div role="main" ng-controller="CalendarCtrl">
    <div id="leftDiv">
      <div id="buttons" class="btn-group">
        <button class="btn btn-success" ng-click="changeView('agendaDay', 'myCalendar1')">Day</button>
        <button class="btn btn-success" ng-click="changeView('agendaWeek', 'myCalendar1')">Week</button>
        <button class="btn btn-success" ng-click="changeView('month', 'myCalendar1')">Month</button>
      </div>
      <div id="hiddenDiv">
        <div id="popover" ng-show="hidePopover.show">
          <div class="form-group">
            <label>New Title</label>
            <input type="text" ng-model="event.title" class="form-control" />
            <label>New Attribute 1</label>
            <input type="text" ng-model="event.attribute1" class="form-control" />
            <label>New Attribute 2</label>
            <input type="text" ng-model="event.attribute2" class="form-control" />
          </div>
        </div>
      </div>
      <hr />
    </div>
    <div id="rightDiv">
      <div class="span12">
        <div id="calendar" class="calendar" ng-model="eventSources" calendar="myCalendar1" ui-calendar="uiConfig.calendar"></div>
      </div>
    </div>
  </div>
</body>

</html>

多亏了这个thread我弄明白了。

我创建了另一个 div 并将其设置为 ng-show='hidePopover.hide' 而原始弹出窗口 div 设置为 ng-show='hidePopover.show' 然后使用 .appendTo() 附加在我的 onEventClick 函数中将原始 div 的内容添加到新的 div。

这是我更新后的代码。

/*
 * myCalendar.js
 */

$scope.hidePopover = {
  show: false
};

$scope.onEventClick = function(event, jsEvent, view) {
  $('#popover').appendTo($('#new_div'));
  var index = $scope.getEventIndex(event.id);
  if ($scope.events[index].state == 'closed') {
    $scope.hidePopover.show = true;
    $scope.event = event;
    $scope.hideOtherPopups();
    $scope.events[index].popoverElement.popover('show');
    $scope.events[index].state = 'open';
    $scope.$apply();
  } else {
    $scope.events[index].popoverElement.popover('hide');
    $scope.updatePopover(event);
    $scope.events[index].state = 'closed';
    $scope.$apply();
  }
};
<!--index.html-->

<div id="popover" ng-show="hidePopover.show">
  <div class="form-group">
    <label>New Title</label>
    <input type="text" ng-model="event.title" class="form-control" />
    <label>New Attribute 1</label>
    <input type="text" ng-model="event.attribute1" class="form-control" />
    <label>New Attribute 2</label>
    <input type="text" ng-model="event.attribute2" class="form-control" />
  </div>
</div>
<div id="new_div" ng-show="hidePopover.hide"></div>