2

I have an AngularJs component having bindings to heroes, which is an array. How to watch this input for array changes? I tried $scope.watch("heroes", ...) and $onChanges, but didn't work so far.

bindings: {
    heroes: '<',
}

Here is my plunker: https://plnkr.co/edit/J8xeqEQftGq3ULazk8mS?p=preview

2 Answers 2

4

The ControllerAs structure needs a special watch expression, since the attributes are not on the $scope.

//This one works and is the best one (> AngularJs 1.5)
$scope.$watch("$ctrl.heroes.length", function () {
  console.log("ControllerAs syntax"); // Triggers once on init
});

//This one works as well
var ctrl = this;
$scope.$watch(() => {
  return ctrl.heroes.length;
}, (value) => {
  console.log("complex watch"); // Triggers once on init
});

See example here: https://plnkr.co/edit/J8xeqEQftGq3ULazk8mS?p=preview

Sign up to request clarification or add additional context in comments.

Comments

0

The issue occurs because $scope.$watch by default doesn't deeply watch objects. Which means since you never destroy/recreate your array, the reference doesnt really change therefore $scope.$watch doesnt see any change. If you watched heroes.length, that primitive would change and your $scope.$watch would fire the corresponding listening function. By using $scope.$watch with the true option you are telling the angular engine to deeply watch all properties. This is pretty intensive to do for large objects because $scope.$watch using angular.copy to track changes

If you were to use $scope.$watchCollection angular would create a shallow copy and would be less memory intensive. So I feel your 3 main options are

Watch heroes.length , add true or use $watchCollection

I feel that using heroes.length would be your best bet, so the code would look like

$scope.$watch('heroes.length',function(){});

The other two options are described below

$scope.$watch('heroes',function(){ //do somthing },true)

or

$scope.$watchCollection

The benefit of using watchCollection is, that it requires less memory to deeply watch an object.

Shallow watches the properties of an object and fires whenever any of the properties change (for arrays, this implies watching the array items; for object maps, this implies watching the properties). If a change is detected, the listener callback is fired.

The obj collection is observed via standard $watch operation and is examined on every call to $digest() to see if any items have been added, removed, or moved. The listener is called whenever anything within the obj has changed. Examples include adding, removing, and moving items belonging to an object or array.

2 Comments

I tried all of your suggestions, but none worked for me. I added a plunker to my question.
It was due to my ControllerAs structure. I added that part at the bottom of your answer. Maybe AngularJs will provide some easier way in the future.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.