← all articles

AngularJS: using $watch with controllerAs

Simon Holmes | 8 March 2015 | AngularJS | Tip of the day

So you're doing all the right things. You've got your Angular application up and running using the controllerAs syntax. And now you want to use $watch in your controller.

Here's an example of a very simple HTML page, declaring a controller Main as vm, with a button and an output.

<body ng-controller="Main as vm">
  <button ng-click="vm.buttonClick()">Click me!</button>
  <p>{{ vm.multiple }}</p>
</body>

Associated to that is the simple controller Main:

function Main () {
  var vm = this;
  vm.original = 1;
  vm.buttonClick = function() {
    vm.original += 1;
    console.log(vm.original);
  }; 
}

Pretty simple, nothing crazy going on here. But what if you want to watch for changes to vm.original?

Typically you'd use $scope.$watch but as you're using the controllerAs syntax you're not necessarily passing $scope into the function. So what do you do?

Can you attach $watch to vm somehow? The answer is no.

$watch must be attached to $scope, so you need to inject $scope into the controller and use $watch as normal. Updating the controller would look like this:

function Main ($scope) {
  var vm = this;
  vm.original = 1;
  vm.buttonClick = function() {
    vm.original += 1;
    console.log(vm.original);
  };
  $scope.$watch('vm.original', function() {
    vm.multiple = vm.original * 2;
  });
}

Here is a JS Bin of it running.

But isn't the point of using controllerAs to avoid the use of $scope? Yes and no. It's really to avoid the misuse of $scope. Using the controllerAs syntax makes you specify a view-model for your controller, keep the actual scope of the controller explicit. This leaves $scope and $rootScope free and uncluttered for when you actually need them.

Free email mini-course on
Full Stack development

Sign up now to receive a free email mini-course covering the MEAN stack and more. Also be the first to know when we release new courses and videos.