2016-12-14 37 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'函數,再次調用工廠。我是不是仍然有這個問題沒有在那個電話上正確更新? –