2014-11-02 107 views
0

我對AngularJS非常陌生,並且一直與KnockoutJS一起工作了很長時間,因爲我仍然沒有充分理解Angular可以跟蹤並且無法跟蹤更改。AngularJS:當底層數據發生變化時,過濾數據不會更新

我正在構建一個應用程序,該應用程序將有一組底層數據,最初我將輪詢和更新,但稍後將改進爲從服務器推送。根據這些數據,應用中的所有數據都將進行轉換或過濾。所以我有一個服務來獲取數據,並同時獲取數據的常用過濾的版本,像這樣:

.factory('Scores', function ($resource, Utils, $q, $interval, $filter) { 
    var scoresResource = $resource('http://localhost:8000/scores'), 
     scoresData = []; 

    $interval(function() { 
     scoresResource.query(function (newScores) { 
      scoresData.length = 0; 
      angular.forEach(newScores, function (dataEntry) { 
       scoresData.push(dataEntry); 
      }); 
     }) 
    }, Utils.TIMES.SHORT); 

    return { 
     getAll: function() { 
      var deferred = $q.defer(); 
      if (scoresData.length > 0) { 
       deferred.resolve(scoresData); 
      } else { 
       scoresResource.query(function (allScores) { 
        scoresData.length = 0; 
        angular.forEach(allScores, function (dataEntry) { 
         scoresData.push(dataEntry); 
        }); 
        deferred.resolve(scoresData); 
       }); 
      } 

      return deferred.promise; 
     }, 
     getByLeagueName: function(leagueName) { 
      return this.getAll().then(function (allScores) { 
       return $filter('filter')(allScores, function (score) { 
        return score.League === leagueName; 
       }) 
      }) 
     } 
    } 
}); 

而我只是控制器取過濾後的數據,並將其添加到的範圍。

.controller('LivescoresCtrl', function ($scope, $stateParams, Leagues, Scores, $interval, Utils) { 
    Scores.getByLeagueName($stateParams.leagueName).then(function (scores) { 
     $scope.scores = scores; 
    }); 
}) 

但是,當基礎數據更新時,似乎過濾的數據不會自動更新。我想避免在視圖中使用過濾器,因爲有時我需要以難以實現的方式將數據組合在一起。

所以我想我的問題是爲什麼這不更新時,主要數據更新,這是一個有效的方法在一個角度的世界。我可以在後端查找所有數據的變體,但由於這是一款移動應用程序,並且在任何時候都需要應用程序中的所有數據,所以我不想僅僅爲了組合或過濾數據而提出額外請求。

感謝,

回答

0

你只設置控制器上的一次數據,使用「getByLeagueName」返回的承諾。一個承諾只能解決一次!

我不確定ko.computed究竟做了什麼。但是,通過使用服務內部的過濾器,您在getByLeagueName之內創建了一個與原始數組無關的新數組。新陣列「不知道它從哪裏來」!

看來你試圖實現輪詢更新,你應該在控制器內部而不是服務內部進行更新。將服務看作後端邏輯的容器,不需要訪問示波器 - 這就是控制器的用途。只要你不直接使用範圍,Angular將不會更新可見數據,因爲這是Angular應用程序獲取顯示數據的唯一地方。


典型的使用過濾數據的Angular方法是:在獲取它之後,在控制器上提供原始數據。然後在視圖(HTML)中使用過濾器,即:<div ng-repeat="entry in data | filter: someFilter">。請參閱ng-filter。通過這種方式,Angular知道原始數據何時更改,再次運行過濾器,並且UI將更新得毫不費力。

如果您確實需要在視圖之外的其他地方使用過濾的數據 - 並確保您這樣做 - 那麼可以採取一些方法。一種是使用該服務通知控制器數據更改:通過$rootScope.$on收聽控制器內部的事件,並通過$rootScope.$broadcast在服務中發出該事件。

你也可以看看this repository,它採用基於承諾的方法來輪詢數據,也許它適合你的任務。

+0

感謝您的迴應,我擔心可能是這樣。所以,由於承諾只解決一次,從承諾返回的數組不是原來的更新數據相同的數組,然後角無法跟蹤任何更改。 我真的不希望把這個過濾/發現在控制器中,因爲它會很常見,然後將不得不重複很多。有沒有什麼角度可以與ko.computed相媲美,只要它的任何依賴關係發生變化就會更新?或者,也許更好的方式來構建一個應用程序? – 2014-11-02 12:22:25

+0

我已經給我的答案添加了一些註釋。 – yerforkferchips 2014-11-02 17:32:58

相關問題