嵌套回调范围和rootScope AngularJS

时间:2016-05-11 01:43:03

标签: javascript angularjs

我在Angular中有以下控制器,它从DB读取一些记录,然后将它们输出到日历中。问题是events数组返回为空。我已经尝试使用$ rootScope.events作为替代,但是这会产生错误“concat不是undefined的函数。”我究竟做错了什么?嵌套作用域有一些诡计吗?

我也刚刚意识到每个活动变量在内部回调中也是未定义的。我认为这是我缺乏的一般知识的一部分。

app.controller('Calendar', ['$scope','$rootScope','$resource','moment', function($scope, $rootScope, $resource ,moment) {

    var Activities = $resource('/api/activities');
        Activities.query(function(activities){
            $rootScope.activities = activities;
            //console.log($rootScope.activities);   
        });

    //console.log($rootScope.activities);

     var vm = this;
     var events = [];

    //define the calendar on rootScope, so it has access to the Events data from the other controllers
    $rootScope.calendar = new moment();

    angular.forEach($rootScope.activities, function(eachActivity){
        //console.log(eachActivity.events);
        if (eachActivity.events.length > 0){
            angular.forEach(eachActivity.events, function(eachEvent, eachActivity){
            console.log(eachEvent);    
            var entry = {
                    title: eachActivity.title,
                    type: "warning",
                    startsAt: eachEvent.startDate,
                    endsAt: eachEvent.endDate,
                    incrementBadgeTotal: true
                }

            events.concat(entry);

            }); 
        }
    });

    vm.events = events;
    console.log(vm.events);

    vm.calendarView = 'month';

    vm.viewDate = moment().startOf('month').toDate();
    vm.isCellOpen = true;

}]);

2 个答案:

答案 0 :(得分:0)

这里有一些事情发生:

1)concat()方法返回一个新数组,该数组由调用它的数组组成,并与作为参数提供的数组和/或值连接。您需要分配vaues:events = events.concat(entry),以便它们在下一次迭代时保留。

2)您已嵌套Angular Loops。通常是必要的,但请注意您的命名约定。

angular.forEach($rootScope.activities, function(eachActivity){
        angular.forEach(eachActivity.events, function(eachEvent, eachActivity)

这里你的循环共享相同的参数名称。这是非常不鼓励的,因为它确实会让开发人员试图理解被迭代的对象的范围。我建议确保您的名字始终是唯一且明确的范围。

3)因为你要覆盖你的参数名称,你对title: eachActivity.title的调用将会查看内部循环第二个参数,在这种情况下是forEach中事件的KEY循环eachActivity.events对象。键没有属性,它们总是字符串 - 因此你的eachActivity变量已定义,但它没有属性。

我建议改变这些内容,然后根据所取得的进展编辑你的帖子。

答案 1 :(得分:0)

要解决您的问题,请更改

angular.forEach(eachActivity.events, function(eachEvent, eachActivity)

angular.forEach(eachActivity.events, function(eachEvent)

第二个参数不是必需的,因为外部循环中已经定义了eachActivity

同时将events.concat(entry);更改为events.push(entry);

此外,不是在$ rootScope上定义日历,而是创建一个日历工厂,并将其注入您需要访问日历数据的控制器中。有许多原因可以解释为什么这样做更好,但最简单的是$ scope不适合在控制器之间共享数据。它们主要用作视图模型,用于在视图和控制器之间绑定数据。

编辑(有关创建工厂的更多详细信息)

您可以像这样定义工厂

app.factory('CalendarService', [function(){
    var calendarEvents = [];  // or {} or even null depending on how you want to use the variable
    return {
        calendarEvents : calendarEvents
    };
}]);

在你的控制器中,

app.controller('Calendar', ['$scope','$rootScope','$resource','moment', 'CalendarService', function($scope, $rootScope, $resource ,moment, CalendarService) {
    ...
    // instead of $rootScope.calendar = new moment (and I don't understand why you are assigning this to a moment but that's another conversation
    CalendarService.calendarEvents = events;
}]);

您需要做的只是将CalendarService注入您需要使用事件数据的每个控制器,它将在calendarEvents字段中提供。