嵌套回调范围和rootScope AngularJS



Angular中有以下控制器,它从DB中读取一些记录,然后将它们输出到日历中。问题是事件数组返回为空。我曾尝试使用$rootScope.events作为替代,但这会给出一个错误"concat不是未定义的函数"。我做错了什么?嵌套作用域有什么花招吗?

我还刚刚意识到,每个Activity变量在内部回调中也是未定义的。我想这只是我所缺乏的一般知识的一部分。

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;
}]);

要解决眼前的问题,请更改

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

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

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

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

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

EDIT(创建工厂的更多详细信息)

你可以定义这样一个工厂

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字段中可用。

这里发生了一些事情:

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

2) 您已经嵌套了角度循环。通常是必要的,但要小心您的命名约定。

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

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

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

我建议修改这几件事,然后根据进展编辑你的帖子。

最新更新