不使用push()时,$ scope中的AngularJS工厂属性未更新

时间:2013-09-02 08:06:59

标签: angularjs angularjs-scope angularjs-service

我有一个从外部源检索数据的工厂。一旦我得到数据,我就会使用第二家工厂按照一定的标准对其进行过滤。

将工厂属性分配给范围。

现在当我在工厂里这样做时,它不会更新范围:

factory.foo = [{id:1,name:'foo'}]; // doesn't work
因此,第二家工厂的过滤器也不起作用

factory.foo = Filter.filter(); // doesn't work

虽然这有效:

factory.foo.push({id:1,name:'foo'}); // works

有没有人知道这是否有意以及为什么会这样,以及如何解决它?

Full Sample plus plunkr

app.factory('Foo',function(Filter) {
  var factory = {
    foo:[],
    getDataForFoo:function() {
      factory.foo = Filter.filter(); // doesn't work
      //factory.foo = [{id:1,name:'foo'},{id:1,name:'foo'}]; // doesn't work
      //factory.foo.push({id:1,name:'foo'}); // works
    }
  };
  return factory;
});

app.factory('Filter',function() {
  var factory = {
    filter:function() {
      var arr = [];
      arr.push({id:1,name:'foo'});
      return arr;
    }
  }
  return factory;
});

app.controller('MainCtrl', function($scope,Foo) {
  $scope.test = 'running';
  $scope.foo = Foo.foo;

  $scope.click = Foo.getDataForFoo;
});

Plunkr

2 个答案:

答案 0 :(得分:12)

问题是您的工厂会将引用替换为Factory.foo。初始化范围时,$scope.foo包含对数组的引用(空)。当您致电Foo.getDataForFoo时,它会在内部将引用更改为Factory.foo,但您的范围仍然保留对前一个数组的引用。这就是使用push的原因,因为它不会更改数组引用,而是更改数组内容。

有几种方法可以解决这个问题。如果没有所有不同的选项,最简单的方法是将$scope.foo包装在一个函数中,返回Factory.foo。这样,Angular将检测摘要周期中的引用更改,并相应地更新视图。

app.controller('MainCtrl', function($scope,Foo) {
  $scope.test = 'running';
  $scope.foo = function() { return Foo.foo };

  $scope.click = Foo.getDataForFoo
});

// And in the view (the relevant part)

<ul ng-repeat="elem in foo()">
  <li>{{elem.id}} {{elem.name}}</li>
</ul>
<a href="" ng-click="click()">add</a>

答案 1 :(得分:1)

@ Simon-Belanger的回答是正确的,他提出了一个可行的解决方案。

另一种选择是清空数组并将新项目推入其中(例如,用于刷新事件),而不是通过为其分配新数组来重置引用。您可以通过分配长度myArray.length = 0来截断数组,然后您可以遍历新集合以通过array.push()填充新条目