2014-11-02 92 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

相关问题