2016-12-14 21 views
2

私はAngular 1.5.9angular-route 1.5.9を使用しています。私は実用的な解決策を持っていますが、DOMを更新するには$scope.$apply()が必要であると私には理解できません。

ng-repeatとして使用されている配列を更新するために、工場とコントローラを使用しています。私は、ダイジェストサイクルが引き起こされていないことを理解しています。そのため、$scope.apply()を使用する必要がありますが、理由はわかりません。ここで失敗しているコードは次のとおりです。

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

そしてHTMLのngのリピート部分のHTMLは次のようになります:

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を処理しています

<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アレイをクリアし、それぞれをプッシュして問題を解決しなかったループを作成しようとしました。私はまだDOMを更新するために$scope.$apply()が必要でした。

それは場合に役立ちます私はここに利用できる全体のレポ(特定のコミットリンク)を持っている:https://github.com/LukeSchlangen/solo_project/tree/df72ccc298524c5f5a7e63f4a0f9c303b395bafa

+0

変更 'VARの自己=この;' VARの自己= $スコープ 'には、'あなたの配列、 '自己を更新する必要があります。ゲーム ' – tsuz

答えて

2

このコードの実行が角度のパービーの外にあるので、角度は、ここでの変更を監視されていません。約束の結果を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の答えに示すように、重要なデータの解決方法をお勧めします。 もう1つの選択肢は、コンテキストローディングインジケータを使用して、素晴らしいUXを提供することです。 – 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'関数を呼び出して、再びファクトリを呼び出します。その通話で正しく更新されていないという問題はまだ解決できませんか? –

関連する問題