范围变量更新但不是视图

时间:2013-12-13 15:30:34

标签: javascript angularjs

我有以下功能,可以建立一个田径赛事和课程列表。我必须显示事件/类组合是否为“正式”,这是通过从后端收集官方组合列表并设置值event.isOfficial=true来完成的,如果返回的组合与组合相匹配要显示。

competitionsService.checkIsOfficial(selectedclasses, selectedevents)
  .then(function (data) {
    //Here we are building the class / event list and checking if the event is official or not
    $scope.currentEditItem.classes.forEach(function (cls) {
      cls.events = selectedEvents;
      cls.events.forEach(function (eventtype) {
        eventtype.forEach(function (event) {
        event.isOfficial = false; // By default no class / events combinations are official
        data.forEach(function (item) {
          if (item.idClass == cls.id && item.idEvent == event.id) {
            event.isOfficial = true;
          }
        });

        if ($scope.currentEditItem.classevent[cls.id][event.id].selected) {
          $scope.addTag(event, cls.eventtags[event.intType],
          $scope.currentEditItem.events[event.intType], event.intType, "classevents_" + cls.id + "_", false); 
          // Update the event tags
          $scope.currentEditItem.classevent[cls.id][event.id].selected = !$scope.currentEditItem.classevent[cls.id][event.id].selected;
        }
      });
    });

    $scope.currentEditItem.classesbysex[cls.intSex].push(cls);
  });
});

相关的html如下所示:

  <ul class="inline">
    <li ng-repeat="event in cls.events[eventtype.intType]" class="titlecell">
        <div ng-click="setChecked(cls, event, cls.eventtags[eventtype.intType],currentEditItem.events[eventtype.intType],eventtype,'classevents_'+cls.id+'_')"
             class="checkbox-div" name='event{{event.id}}'
             id='classevents_{{cls.id}}_{{event.id}}'>
            <i ng-class="{'icon-ok': currentEditItem.classevent[cls.id][event.id].selected}" class="iconpos"></i>
        </div>
        <div class="titlecell" ng-class="{warn:!event.isOfficial}">{{ event.idEvent }}: {{ event.strName }} - {{ event.isOfficial }} </div>
    </li>
</ul>

问题在于即使在范围内将event.isOfficial设置为true(当然在调试器中已经检查过),它也不会在视图中更新。

注意: 在调用competitionsService.checkIsOfficial之前加载页面。这将转到后端,并在返回承诺后更新DOM。但是,正确显示此回调的其余数据。

$scope.$apply()会引发$digest is already in progress

的错误

event.isOfficial = true以上三行,我设置了event.isOfficial = false。这反映在视图中。测试{{ event.isOfficial }}始终显示false

今天工作几个小时后,我的头发很少。关于我可能做错的任何想法将不胜感激。

谢谢!

更新:

花了一段时间才能获得正确的数据,但我有一个Plunk工作: http://plnkr.co/edit/pBoM4BHlx4h7Cw2jEIfG?p=preview

1 个答案:

答案 0 :(得分:1)

最好的,因为我可以告诉您的问题是您在重复更改相同事件的isOfficial标志,而不是在独立副本上执行操作。通过在正确的位置应用angular.copy(),可以轻松解决此问题。

作为附加奖励,我删除了一个嵌套循环,将其替换为简单的地图。

在plunker中,$scope对象上似乎缺少一个函数,所以我对它进行了评论。

competitionsService.checkIsOfficial(selectedclasses, selectedevents)
    .then(function (data) {
        /// prevent a nested forEach-loop by using a map.
        var map = {};
        data.forEach(function (item) {
            map[ [item.idClass,item.idEvent] ] = true;
        });

        //Here we are building the class / event list and checking if the event is official or not
        $scope.currentEditItem.classes.forEach(function (cls) {

            /// make a deep copy so the event-objects are independant.
            cls.events = angular.copy(selectedEvents);

            cls.events.forEach(function (eventtype) {
                eventtype.forEach(function (event) {
                    event.isOfficial = map[ [cls.id, event.id] ] !== undefined;

                    if ($scope.currentEditItem.classevent[cls.id][event.id].selected) {
                        /// !! $scope.addTag does not exist in the plunker example.
                        /// $scope.addTag(event, cls.eventtags[event.intType], $scope.currentEditItem.events[event.intType], event.intType, "classevents_" + cls.id + "_", false); 

                        // Update the event tags
                        $scope.currentEditItem.classevent[cls.id][event.id].selected = !$scope.currentEditItem.classevent[cls.id][event.id].selected;
                    }
                });
            });

            $scope.currentEditItem.classesbysex[cls.intSex].push(cls);
        });
    });