4

I have a fairly straightforward AngularJS question to which I cannot seem to find an answer:

How would I go about using $scope.$watch() in a directive controller while also using the controllerAs and bindToController options?

Please let me know if you need any clarification on what I mean exactly.

Dean Zaslow
  • 87
  • 2
  • 9

1 Answers1

11

Well, $scope.$watch watches for expressions so assuming you're binding your controller to the name vm (e.g. controllerAs: 'vm') you should use

$scope.$watch('vm.somethingToWatch', function(newval, oldval) {...})

You will need to still inject the $scope though, since $watch is not available on controller instances by themselves.

rinogo
  • 8,491
  • 12
  • 61
  • 102
ArtoAle
  • 2,939
  • 1
  • 25
  • 48
  • To inject `$scope` properly, do I need to use `$injector`, or would I just include it in my controller? (i.e. `controller: function($scope) {`) – Dean Zaslow Mar 08 '16 at 14:55
  • Would I still use the `controllerAs` name (e.g. `vm`) if the `$scope.$watch` function exists _inside_ the controller itself, with a `this` variable? i.e. `var self = this;` `self.total = someCode;` `$scope.$watch('self.total', function()` vs. `$scope.$watch('vm.total', function()` – Dean Zaslow Mar 08 '16 at 14:57
  • Yeah, you can have it simply injected in the controller function as in `function($scope)`. For the latter question, yeah, the expression is evaluated as it would happen inside the template, so `vm.total` :) – ArtoAle Mar 08 '16 at 15:03
  • ^ Thank for the concise answers - much appreciated. – Dean Zaslow Mar 08 '16 at 15:17
  • 1
    Newbie question - This seems weird to me - We're binding the scope to the controller. To detect changes to a variable that's now on the controller, instead of doing so "directly", we have to ask the scope to watch for changes? Is there no Angular way to do this without involving the scope (besides the initial `bindToController`, of course)? – rinogo Oct 03 '16 at 20:32
  • There are two main reasons for the bindToController I believe: to allow class-style controller to work nicely and more importantly, to always guarantee a `.` in angular templates, making sure you don't fall in scope inheritance nuisance. It doesn't mean that handling the scope is now deferred to the controller, all scope specific method are still only accessible with it (e.g. `scope.$apply`, `scope.$watch`, `scope.$broadcast`, `scope.$on` and so on...) – ArtoAle Oct 12 '16 at 17:03