2016-12-14 39 views
2

我正在使用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 

角路由器正在处理我的controllerAs像这样:

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

以及用于在HTML的NG-重复部分的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

+0

变化'无功自我=这一点;'到'无功自我= $范围;'应该更新您的阵列,'自我。游戏' – tsuz

回答

2

角度看的不是这里的变化,因为这个代码的执行是角的purvey之外。使用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?

+0

当我运行我的'addGame'函数时,这似乎工作的很好,但它似乎并没有在初始加载时显示游戏 - 当我第一次调用getGames()时。我猜测我不能在初始加载时调用'$ q'库。 –

+0

您应该可以在初始加载时调用它,但是在控制器运行之前不会加载数据。这意味着您的视图将加载,但在数据被提取并且承诺解决之前,您不会看到游戏。如Yaser的答案所示,我会推荐重要数据的解析方法。 另一种选择是上下文加载指示器,它可以提供一个很好的用户体验。 – ginman

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; 
}); 
+0

酷!但是,当我调用'addgames'时,它会解决它不更新DOM的问题吗? –

+0

控制器不会初始化,直到发生解决方案@LukeSchlangen – Yaser

+0

我认为这对我的初始页面加载非常有用。然后我在控制器的底部调用了一个'addGame'函数,再次调用工厂。我是不是仍然有这个问题没有在那个电话上正确更新? –

相关问题