Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angularjs: 'controller as syntax' and $watch

Just bind the relevant context.

$scope.$watch(angular.bind(this, function () {
  return this.name;
}), function (newVal) {
  console.log('Name changed to ' + newVal);
});

Example: http://jsbin.com/yinadoce/1/edit

UPDATE:

Bogdan Gersak's answer is actually kind of equivalent, both answers try binding this with the right context. However, I found his answer cleaner.

Having that said, first and foremost, you have to understand the underlying idea behind it.

UPDATE 2:

For those who use ES6, by using arrow function you get a function with the right context OOTB.

$scope.$watch(() => this.name, function (newVal) {
  console.log('Name changed to ' + newVal);
});

Example


I usually do this:

controller('TestCtrl', function ($scope) {
    var self = this;

    this.name = 'Max';
    this.changeName = function () {
        this.name = new Date();
   }

   $scope.$watch(function () {
       return self.name;
   },function(value){
        console.log(value)
   });
});

You can use:

   $scope.$watch("test.name",function(value){
        console.log(value)
   });

This is working JSFiddle with your example.


Similar to using the "test" from "TestCtrl as test", as described in another answer, you can assign "self" your scope:

controller('TestCtrl', function($scope){
    var self = this;
    $scope.self = self;

    self.name = 'max';
    self.changeName = function(){
            self.name = new Date();
        }

    $scope.$watch("self.name",function(value){
            console.log(value)
        });
})

In this way, you are not tied to the name specified in the DOM ("TestCtrl as test") and you also avoid the need to .bind(this) to a function.

...for use with the original html specified:

<div ng-controller="TestCtrl as test">
    <input type="text" ng-model="test.name" />
    <a ng-click="test.changeName()" href="#">Change Name</a>
</div>

AngularJs 1.5 supports the default $ctrl for the ControllerAs structure.

$scope.$watch("$ctrl.name", (value) => {
    console.log(value)
});

you can actually pass in a function as the first argument of a $watch():

 app.controller('TestCtrl', function ($scope) {
 this.name = 'Max';

// hmmm, a function
 $scope.$watch(function () {}, function (value){ console.log(value) });
 });

Which means we can return our this.name reference:

app.controller('TestCtrl', function ($scope) {
    this.name = 'Max';

    // boom
    $scope.$watch(angular.bind(this, function () {
    return this.name; // `this` IS the `this` above!!
    }), function (value) {
      console.log(value);
    });
});

Read an interesting post about controllerAs topic https://toddmotto.com/digging-into-angulars-controller-as-syntax/


You can use $onChanges angular component lifecycle.

see documentation here: https://docs.angularjs.org/guide/component under Component-based application section