How can I view a property for changes in a filtered array of objects when I filter that same property?

How to do it:

$scope.$watch('item.completed', function(to, from){ …

      

combined with this:

<li ng-repeat="item in items | filter:{completed: true}" ng-controller="ItemCtrl">
      

Live plunker example: http://plnkr.co/edit/pdFkEmxyqrzS6mc2AYo2?p=preview

At the present time, when I change the property of the item

object completed

, $watch()

does not start.

I suspect it has something to do with referencing the property of the filter properties, but how do I do it otherwise? I've also tried $watch(…, …, true)

and $watchCollection()

but has no effect.

+3


source to share


4 answers


You can listen for the scope destroy event and get the value from the event object:



.controller('ItemCtrl', ['$scope', function($scope){
    $scope.$on('$destroy', function(o){log(o.targetScope.item.name + '(' + o.targetScope.item.completed + '):destroyed')});
    $scope.$watch('item.completed', function(to, from){
      log(from + ' --> ' + to);
    });
  }]);

      

+2


source


I'm still not entirely sure I understand the end goal. I think you are saying that you want to be able to register when an item changes in the filtered list. I can think of a couple of imperfect approaches.

  • Forget about the watch completely. Just call the function on ng-change

    to enter the checkbox: http://plnkr.co/edit/IeAt4a31So7zjMJzptIp?p=preview
  • Create a deep scan of an array of elements through $scope.$watch('items', listener, true)

    . The third argument true

    will cause the object check to be used , after which you can compare after the array and log states that changed each time: http://plnkr.co/edit/gg5DPWJhx8syhNhelFOT?p=preview


Not only exactly watch

which gives you a certain changed item in the list, but I think you can get what you eventually need to do via these routes.

+1


source


You should be able to run the clock function if you are using ng-show instead of filtering.

<li ng-repeat="item in items" ng-show="{{item.completed}}" ng-controller="ItemCtrl">

      

0


source


This is a hacky way to do it, but I think it does what the OP wants:

http://plnkr.co/edit/wGRJIGJbALjMQqeffCyF?p=preview

It also proves that jonasnas and PSL were absolutely right.

The idea is to do it in controllers:

  .controller('ItemsCtrl', ['$scope', function($scope){
    $scope.items = [
      {name: 'item 1', completed: true},
      {name: 'item 2', completed: true},
      {name: 'item 3', completed: true},
      {name: 'item 4', completed: false},
      {name: 'item 5'},
      {name: 'item 6', completed: true},
    ];
    $scope.itemsToWatch=[];
    $scope.watchMe = function(item){
      var myIdx = $scope.items.indexOf(item);
      if($scope.itemsToWatch.indexOf(myIdx)==-1){
        $scope.itemsToWatch.push(myIdx);
        $scope.$watch('items[' + myIdx + '].completed', function(to, from){
          log(from + ' --> ' + to);
        });
      }
    };
  }])
  .controller('ItemCtrl', ['$scope',function($scope){
      $scope.$parent.watchMe($scope.item);
  }]);

      

I don't think there would ever be anything like this in the code, but it was interesting to find a way to resolve the issue, and I learned a few things along the way.

0


source







All Articles