AngularJS factory property isn't being updated in $scope when not using push()

倾然丶 夕夏残阳落幕 提交于 2019-12-06 22:51:27

问题


I have a factory that is retrieving the data from an external source. As soon as i get the data, i use a second factory to filter it by a certain criteria.

The factory property is assigned to scope.

Now when i do this in my factory, it doesn't update the scope:

factory.foo = [{id:1,name:'foo'}]; // doesn't work

therefor also the filterin in a second factory doesn't work

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

while this works:

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

Does anyone have an idea if this is intended and why it is like this, and how to solve it?

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


回答1:


The problem is that your factory replace the reference to Factory.foo. When your scope is initialized, $scope.foo holds a reference to an array (empty). When you call Foo.getDataForFoo, it internally changes the reference to Factory.foo but your scope still hold a reference to the previous array. This is why using push works as it doesn't change the array reference, but the array content.

There are a few ways to fix this. Without going in all the different options, the easiest one is to wrap your $scope.foo in a function, returning Factory.foo. This way, Angular will detect a reference change in a digest cycle and will update the view accordingly.

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>



回答2:


@Simon-Belanger answer is correct and he presents a viable solution.

Another option would be to just empty the array and push new items into it (e.g. for a refresh event), rather than resetting the reference by assigning a new array to it. You can truncate an array by assigning to the length: myArray.length = 0 and then you can iterate over the new collection to populate new entries via array.push()



来源:https://stackoverflow.com/questions/18568373/angularjs-factory-property-isnt-being-updated-in-scope-when-not-using-push

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!