为什么$ scope。$ apply更新此数组

时间:2016-12-14 03:31:46

标签: javascript angularjs angular-routing

我正在使用Angular 1.5.9angular-route 1.5.9。我有一个有效的解决方案,但对我而言,我需要$scope.$apply()才能更新DOM。

我正在使用工厂和控制器来更新在ng-repeat内使用的数组。我知道摘要周期没有被触发,这就是为什么我需要使用$scope.apply(),但我不明白为什么。这是失败的代码:

myApp.controller('MyGamesController', ['$http', '$firebaseAuth', 'DataFactory', '$scope', function ($http, $firebaseAuth, DataFactory, $scope) {
  console.log('mygamescontroller running');
  var self = this;
  self.newGame = {}
  self.games = [];

  getGames();

  function getGames() {
        DataFactory.getGames().then(function (response) {
          console.log('returned to controller from factory', response); // logs the correct response including lastest data, but DOM doesn't update
          self.games = response; // self.games is correctly set, but not updated on the DOM
          $scope.$apply(); // Updates the DOM 
        });
  } //end getgames function


  self.addGame = function () {
    DataFactory.addGame(self.newGame).then(getGames);
  }

}]); //end controller

Angular Router正在处理我的controllerAs

  .when('/mygames' ,{
    templateUrl: '/views/templates/mygames.html',
    controller: 'MyGamesController',
    controllerAs: 'mygames'
  })

HTML的ng-repeat部分的HTML如下所示:

  <tbody>
    <tr ng-repeat="game in mygames.games">
      <td>{{game.game}}</td>
      <td>{{game.number_players}}</td>
      <td>{{game.time_to_play}}</td>
      <td>{{game.expansion}}</td>
    </tr>
  </tbody>

顺便说一下,我确实试图清除self.games数组并创建一个循环,推动每个数组,但没有解决问题。我仍需要$scope.$apply()才能更新DOM。

如果有帮助,我可以使用整个仓库(链接特定提交):https://github.com/LukeSchlangen/solo_project/tree/df72ccc298524c5f5a7e63f4a0f9c303b395bafa

2 个答案:

答案 0 :(得分:2)

您可以使用您的routeProvider在页面加载中获取游戏数组,而不是在控制器中获取游戏数组:

由于您的页面已在加载时呈现(该数组为空),因此不会有任何触发摘要周期的事件。

.when("/news", {
    templateUrl: '/views/templates/mygames.html',
    controller: 'MyGamesController',
    controllerAs: 'mygames'
    resolve: {
        games: function(){
            return DataFactory.getGames();
        }
    }
}

在你的控制器中:

app.controller("MyGamesController", function (games) {
    var self = this;
    self.newGame = {}
    self.games = games;
});

答案 1 :(得分:2)

Angular并没有在这里观察更改,因为此代码的执行超出了Angular的支持范围。使用Angular监视承诺结果的最简单方法是使用$q库。

function getGames() {  
    return $q.resolve(DataFactory.getGames().then(function (response) {
      self.games = response; // self.games is correctly set, but not updated on the DOM
    }));
} //end getgames function

$ q承诺由Angular管理,当$ q承诺结算时,它将会运行摘要周期。

您还需要在控制器中包含并注入$ q。

myApp.controller('MyGamesController', ['$q', '$http', '$firebaseAuth', 'DataFactory', '$scope', function ($q, $http, $firebaseAuth, DataFactory, $scope) {

这篇优秀的帖子详细说明了异步调用如何与摘要周期一起使用: How do I use $scope.$watch and $scope.$apply in AngularJS?