【问题标题】:Using gotoDate in fullCalendar with Angular UI在带有 Angular UI 的 fullCalendar 中使用 gotoDate
【发布时间】:2015-10-26 20:00:30
【问题描述】:

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

我尝试过使用gotoDate 方法,我可以看到它可以工作(它也可以从控制台工作),但几乎是在日历恢复到当前日期之后立即进行的。由于我是 AngularJS 的新手,我可能将 gotoDate 放在了错误的位置。但我不知道把它放在别处。

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

$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-model 的手表可以重新渲染 fullcalender,如果是,我该如何设置选择的日期?

更新:我结束了使用 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);

      }

【问题讨论】:

    标签: angularjs fullcalendar angular-ui


    【解决方案1】:

    这是日历的错误。您是第一个在 StackOverflow 上对此发表评论的人。赞一个。

    有几种方法可以解决此问题。它已在 github https://github.com/angular-ui/angular-ui/pull/520 上提出,我们取消指令如何在手表被触发时重新创建自身,这将阻止这种行为。我相信,如果我们能让这种方法在生产中发挥作用,那将是最好的解决方案。

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

    这里是新更新函数在日历指令中的外观的 sn-p。

    /* 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 服务器上经过适当的测试,但它工作正常,因为我目前在生产中使用它。

    【讨论】:

    • 补丁工作正常,但是我在上面的代码中将 exCalender 更改为 uiCalendar,因为我将该属性与我的自定义设置一起使用。在即将发布的版本中,属性名称是否即将更改?
    • 对补丁不起作用的一件事是如果用户更改了视图。它总是恢复到月视图,即默认值。也许我会在一周内抽出一些时间来看看它。
    • 啊,是的,很抱歉将 ex 命名空间留在那里。但是,我也没有注意到您所指的错误。
    • 漂亮!我试试看。
    【解决方案2】:

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

    在你的特殊情况下,你可以这样写:

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

    AngularUI 确实对 eventSource 和 event 进行了监视,每次更改的长度都会调用更新函数。您可以在此处查看源代码:

    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

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

    【讨论】:

    • 啊,就是这么简单 - $scope.calendar。使用 DOM 操作感觉就像是 hack。自发地,手表似乎是要走的路。过几天我会试试这个代码。
    • fullcalendar 现在在 $scope.calendar 上不再可用,它被定义为一个属性,例如 calendar="bob" 将使它在 $scope.bob.fullCalendar() 上可用参见github.com/angular-ui/ui-calendar/pull/12
    • @toxaq 我听不懂他们在那里的谈话。我看到 $scope.calendar 现在不可用了,那我怎么能在没有直接 DOM 编辑的情况下使用 gotoDate 呢?
    • @boi_echos 没有查看任何代码来确认并使用我的示例$scope.bob.fullCalendar().gotoDate()
    【解决方案3】:

    在不更改 Angular-UI 源的情况下解决问题的另一种方法是像这样声明日历:

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

    并且在将monthValyearVal 设置为适当值的范围内有一个viewDisplayHandler 函数,以便在整个日历重新创建之后设置日历上的日期:

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

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

    【讨论】:

    • 我希望使用您的回调方法更改为 eventSource 指定的数据,例如: $scope.eventSourceNew = { url: URL, type: 'GET' }; $scope.addRemoveEventSource($scope.eventSources, $scope.eventSourceNew);不幸的是,当它从不调用 URL 时。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多