How to properly use $watch in a directive inside a "controller as" controller?

1.1k Views Asked by At

Here is my JS code. The objective is to create a directive that changes the associated DOM element visibility on a scope variable change, but here I've just replaced the code by an 'alert' intruction to get a minimal (not) working example.

app.directive( 'myDirective', [ function () {
   return {
       restrict: 'A',
       link: function( scope, element, attrs ) {
           scope.$watch( 'configurationMode', function( newValue ) {
               alert("TOTO");
           }, true );
       }
   };
} ]);

app.controller( 'ControlPanelController', function() {
    this.configurationMode = true;

    // and some additional code that 
    // modifies 'configurationMode'
    // in response to UI events
});

And I use the directive in the HTML in a straightforward way:

<div my-directive>
    ...
</div>

alert('TOTO') is called once at the first digest cycle, but not once after that, even though the configurationMode variable changes value (which I can see on the UI). What is wrong with the code?

This is the first time I use the 'controller as' syntax with my controller. Is this the issue here?

1

There are 1 best solutions below

3
Jerinaw On BEST ANSWER

You have to attach configurationMode to the scope in your controller. scope.$watch only watches properties on the scope.

There's a couple hacks for watching variables attached to your controller. One might be using controller as, say controller as $ctrl, then scope.$watch('$ctrl.configurationMode', function(){}).

I would just using bindings, a two way binding, and pass the value through the bind on your directive... the syntax is different depending on what version of AngularJS/Angular you are using.

.directive( 'myDirective', [ function () {
   return {
       restrict: 'A',
       scope:{
            configurationMode: '='
       },
       link: function(scope, element, attrs) {
           scope.$watch('configurationMode', function(newValue) {
               alert("TOTO");
           }, true);
       }
   };
}]);

then to use it

<div my-directive configuration-mode="$ctrl.configurationMode"></div>

My AngularJS 1.x is a little rusty so check the docs https://docs.angularjs.org/guide/directive I'm guessing you're using an AngularJS 1.x because you have a restrict: 'A' property on your directive.