Join the Stack Overflow Community
Stack Overflow is a community of 6.4 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

How can I listen to angular component binding change and perform actions?

angular.module('myapp')
    .component('myComponent', {
        templateUrl: 'some.html',
        controller: MyController,
        controllerAs: 'myCtrl',
        bindings: {
            items: '<'
        }
    });

now when items changes I want to perform another action using this value,
How can I do it?

share|improve this question
up vote 16 down vote accepted
+100

now when items changes I want to perform another action using this value, How can I do it?

But I want to avoid using the dying $scope

If you don't want to use $scope you can use a property setter to detect any changes e.g. :

class MyController {
    private _items: string[] = []
    set items(value:string[]){
        this._items = value;
        console.log('Items changed:',value);
    }
    get items():string[]{
        return this._items;
    }
}

const ctrl = new MyController();
ctrl.items = ['hello','world']; // will also log to the console

Please note that you shouldn't use it for complex logic (reasons : https://basarat.gitbooks.io/typescript/content/docs/tips/propertySetters.html) 🌹

share|improve this answer
2  
The answer is in TypeScript. Can you toss up something that's ECMAScript (2015 is fine since I'm using babel)? – Chris Mar 21 at 20:21
1  
@Chris I've just posted an ES5 version below: stackoverflow.com/a/36890636/206614 – jfrej Apr 27 at 13:02

You can add the $onChanges method to the controller object, as follows:

$onChanges: function (changes) {
  if (changes.items) 
   this.performActionWithValueOf(changes.items);
}

Requires AngularJS >= 1.5.3 (not well-documented as of yet)

Reference: http://blog.thoughtram.io/angularjs/2016/03/29/exploring-angular-1.5-lifecycle-hooks.html

share|improve this answer
    
In case it helps anyone else: note that this only works with the newer one-way binding syntax ("<"), and not with the more "traditional" 2-way binding using "=". It's documented, but easy to miss, as I learned the hard way. :-p – Marc Stober Nov 29 at 18:47

Here's an ES5.1 version of basarat's answer:

function MyController() {
  var items = [];

  Object.defineProperty(this, 'items', {
    get: function() {
      return items;
    },

    set: function(newVal) {
      items = newVal;
      console.log('Items changed:', newVal);
    }
  });
}

Using Object.defineProperty(). Supported by all major browsers and IE9+.

share|improve this answer
    
Fantastic thank you. I was playing around with the defineProperty but usually ended up I endless loops, I hadn't tried the "this" in the defineProperty. – Chris Apr 27 at 18:42

I've discovered a way but not sure it's the most efficient. First bring in $scope as a dependency and set it to this._scope or the like in your constructor. I have the following then in my $onInit function:

this._scope.$watch(() => {
    return this.items;
  },
  (newVal, oldVal) => {
    // Do what you have to here
  });

It's highly inspired by the answer here: Angularjs: 'controller as syntax' and $watch

Hope it helps, it's what I'm going to use until I'm told otherwise.

share|improve this answer
    
Thanks for your answer! But I want to avoid using the dying $scope – Dor Cohen Mar 1 at 9:17
1  
Yeah, it felt dirty since the "this" variable should really be the scope and have the watching setup. I've now had to do this in almost all of my components! The toggling of the value from null to something has worked fine, but just changing the contents of the watched items still remains a mystery. – Chris Mar 4 at 19:53

Currently you can't use angular watchers without $scope as change detection is based around $scope. Even if you use expressions in HTML it would delegate watch functionality to $scope.

Even if you create some other mechanism to watch you will need to remember to unwatch manually - and with $scope it's done automatically.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.