使用Angular UI在fullCalendar中使用gotoDate

时间:2013-03-28 08:11:08

标签: angularjs fullcalendar angular-ui

我使用带有Angular UI的FullCalendar设置日历。它工作正常,我可以很好地切换事件类别,但每次更新eventSource时,日历视图都设置为当前日期。

我已经尝试使用gotoDate方法,我可以看到它有效(它也可以在控制台上运行),但几乎是在日历恢复到当前日期之后。由于我是AngularJS的新手,我可能会将gotoDate置于错误的位置。但我无能为力地把它放在其他地方。

我正在使用一个返回一堆事件对象的服务,并将它们推送到eventSources,即日历元素的ng-model。没有什么特别的,在我的控制器中:

$scope.eventSources = [];
var promise = UserCalendarEvents.get(groupName);
promise.then(
    function(events) {
        $scope.eventSources.push(events);
        $('#events-calendar').fullCalendar('gotoDate', 2012, 11);
    },
    function(reason) {
        console.log('Error: ' + reason);
    }
);

在这种情况下,将获取事件并填充$scope.eventSources。然后将日历视图设置为2012年12月,之后几乎立即将视图切换到当前日期。它是某种类型的ng模型手表重新渲染全日历,如果是这样,我如何设置选择日期?

更新:我结束了使用joshkurz修复程序,但是在一个修改版本中尊重所选视图,即如果用户选择了basicWeek并更改了源数据,则视图不应更改为例如月份视图。这就是我的用户所需要的。

    function update() {
        scope.calendar = elm.html('');
        var view = scope.calendar.fullCalendar('getView');
        var m;
        var xtraOptions = {};
        //calendar object exposed on scope
        if(view){
          var viewDate = new Date(view.start);
          if(m !== 'Invalid Date'){
            y = viewDate.getFullYear();
            m = viewDate.getMonth();
            d = viewDate.getDate();
            if(!isNaN(y) && !isNaN(m) && !isNaN(d)){
              xtraOptions = {
                year: y,
                month: m,
                date: d
              };
            }
          }
          view = view.name; //setting the default view to be whatever the current view is. This can be overwritten.
        }
        /* If the calendar has options added then render them */
        var expression, 
            options = { defaultView : view, eventSources: sources };
        if (attrs.uiCalendar) {
            expression = scope.$eval(attrs.uiCalendar);
            // Override defaultView if is set in ui-calendar attribute - OK? 
            if (expression.defaultView) {
                expression.defaultView = view;
            }     
        } else {
            expression = {};
        }
        angular.extend(options, uiConfig.uiCalendar, expression, xtraOptions);
        scope.calendar.fullCalendar(options);

      }

3 个答案:

答案 0 :(得分:3)

这是日历的错误。你是第一个在StackOverflow上对它说些什么的人。奖励。

有几种方法可以解决这个问题。它是在github https://github.com/angular-ui/angular-ui/pull/520上提出的,我们废除了指令在触发监视时重新创建的方式,这将阻止这种行为。我相信如果我们能够将这种方法用于生产,那么它将是最好的解决方案。

在此之前,修复方法是从view.start字段创建的日期对象中获取当前月份。应将此月份添加到用于呈现日历的选项中。

以下是新更新函数在calendar指令内部应该是什么样的片段。

/* update the calendar with the correct options */
        function update() {
          scope.calendar = elm.html('');
          var view = scope.calendar.fullCalendar('getView');
          var m;
          var xtraOptions = {};
          //calendar object exposed on scope
          if(view){
            var d = new Date(view.start);
            m = new Date(view.start);
            if(m !== 'Invalid Date'){
              m = m.getMonth();
              if(!isNaN(m)){
                xtraOptions = {
                  month: m
                };
              }
            }
            view = view.name; //setting the default view to be whatever the current view is. This can be overwritten.
          }
         // console.log(m)
          /* If the calendar has options added then render them */
          var expression,
            options = {
              defaultView : view,
              eventSources: sources
            };
          if (attrs.exCalendar) {
            expression = scope.$eval(attrs.exCalendar);
          } else {
            expression = {};
          }
          angular.extend(options, uiConfig.exCalendar, expression, xtraOptions);
          scope.calendar.fullCalendar(options);
        }

这在angular-ui CI服务器上没有经过适当的测试,但它正常,因为我目前在生产中使用它。

答案 1 :(得分:1)

在不更改Angular-UI源的情况下解决问题的另一种方法是声明日历,如下所示:

<div ui-calendar="{viewDisplay:viewDisplayHandler,month:monthVal,year:yearVal}" ng-model="eventsArr"></div>

要在范围内设置viewDisplayHandler函数,将monthValyearVal设置为适当的值,以便在整个日历重新设置之后在日历上设置日期:< / p>

$scope.viewDisplayHandler = function(view) {
    var viewStart = view.start;
    $scope.yearVal = viewStart.getFullYear();
    $scope.monthVal = viewStart.getMonth();
}

这是我在GitHub上发出pull请求之前解决的问题。它不是我想的最佳方法,但我已经在生产中使用了一段时间,它似乎没问题,也不需要更改Angular-UI的代码。

答案 2 :(得分:0)

使用AngularUI将FullCalendar包装在指令中,可以通过$ scope.calendar访问日历对象。 “AngularJS Way”是为了避免控制器中的直接DOM操作。

在你的特定情况下,你会写这个:

$scope.calendar.fullCalendar('gotoDate', 2012, 11);

AngularUI确实监视eventSource和事件,每次更改时都会调用更新函数。您可以在此处查看来源:

https://github.com/angular-ui/angular-ui/blob/master/modules/directives/calendar/calendar.js

每次事件模型更改时,您都可以看到$ scope.calendar中的日历对象使用一组新事件进行重新创建。这就是为什么您的日期更改未通过 - 正在添加事件,触发更新,日期更改进入,整个日历更改以及日期更改丢失。

在不改变AngularUI代码的情况下,两个(不是最好的)东西出现在我面前:

  1. 您可以使用AngularJS的$ timeout服务并等待一组 加载事件后的时间,日历已完成更新, 然后调用你的日期更改。

  2. 您可以在触发日期更改的范围上添加$ watch 每次日历对象发生变化时:

    http://plnkr.co/edit/Ww08VX?p=preview

  3. 我在上面创建了这个例子。在test()方法中,我只是通过一个承诺(它们将在2013年3月添加)将一些虚假数据加载到事件中,然后将日期更改为2012年12月。我正在观看$ scope.calendar并且每次更改(在指令中触发更新)我重新发送date命令。你应该被送到2012年12月,甚至没有看到新活动进入,但如果你回到2013年3月,他们应该在那里。我把手表放在另一个手表上。然后假设你将使用一些值来动态设置日期。