Angular-styleguide: $scope.watch with controller as syntax

Created on 17 Jul 2015  ·  12Comments  ·  Source: johnpapa/angular-styleguide

In your example of watching with a controller as syntax (Style Y032) you don't make it clear that you will couple the controller to its view because your snippet will only work if there is SomeController as vm in your view.

For me this is a disadvantage in using the whole controller as syntax. You could solve this with using the function notation of $scope.watch or write something about the problems using your current approach.

Angular 1 enhancement help wanted

Most helpful comment

I think that this summarizes the discussion


controllerAs $watch

[Style [Y999](#style-y999)]
  • Avoid using $scope.$watch. Use ng-change or a custom directive instead.

    _Why?_: Watches are harder to test and they are also bad for performance because they are evaluated in every $digest loop.

    /* avoid */
    function SomeController($scope) {
    var vm = this;
    
    $scope.$watch(function () {
        return vm.title;
    }, doSomething);
    
    function doSomething() {
    }
    }
    
    <!-- recommended -->
    <input type="text" ng-model="vm.title" ng-change="vm.doSomething()"/>
    
    /* recommended */
    function SomeController() {
      var vm = this;
      vm.doSomething = doSomething;
    
      function doSomething() {
      }
    }
    

All 12 comments

PR if you like

so do you think I should just write about the problems using controller as with $scope.$watch or should I introduce the functions notation like

$scope.$watch(function () {
    return vm.title;
}, function(current, original) {
    $log.info('vm.title was %s', original);
    $log.info('vm.title is now %s', current);
});

replacing the old example or should I compare both?

If I understand your structure I would compare both and use your avoid and recommended syntax.

Brrrr. Watching inside a controller an anti-pattern. You really don't need it in this example anyway; would be better to add change event binding (and I believe that's what you'll be doing in Ng2).

I'd prefer this discussion to be a sub-section of the "ControllerAs" which begins by urging folks to avoid watching inside a controller. Then, "if you must", I'd just go with @Jandalf version and not make too big a deal about the risks of evaluating the 'vm.title' expression. Just say: "do it this way".

what do you think about this preview:

controllerAs and $watch

[Style Y999] // whats the next free number?

Note: Create watches with caution as they add more load to the digest cycle. Use ngChange instead.

  • use the function notation of $scope.$watch to watch for changes

_Why?_: the controller could be bound to another value then vm

So if you really need to watch a value use this pattern:

  <input ng-model="vm.title"/>
  function SomeController($scope, $log) {
      var vm = this;

      $scope.$watch(function () {
          return vm.title;
      }, function(current, original) {
          $log.info('vm.title was %s', original);
          $log.info('vm.title is now %s', current);
      });
  }

Hmmmm

It has to be clear that watching in controllers should be avoided. use ngChange instead. Or move the watch to a directive. thoughts?

Then a new rule for how to use watch with controllerAs that replaces or updates what I have in there.

Agree with you, John.

It isn't clear enough that a watch in a controller is to be avoided and that listening to the change event OR writing a directive is preferred. Should have a "why" for this advice too (why watches in controllers are bad)

The advice on how to do it _if you must_ should be separate point and should begin with a repeat strong warning against.

THEN I'd like to see a case for why I'd do it at all. I don't see one here. Can't actually think of one. Can you?

Without such an example, I would be reluctant to include this advice at all.

Also, the "Why" in this text confused me. It's a "why" for the specific technique of avoiding dependence on the "vm" name. That's secondary to the real why, which is why you'd ever watch in a controller. It makes sense only if preceded by a "don't do it this way" example.

More work to be sure but necessary I think.

proposal anyone?

I think that this summarizes the discussion


controllerAs $watch

[Style [Y999](#style-y999)]
  • Avoid using $scope.$watch. Use ng-change or a custom directive instead.

    _Why?_: Watches are harder to test and they are also bad for performance because they are evaluated in every $digest loop.

    /* avoid */
    function SomeController($scope) {
    var vm = this;
    
    $scope.$watch(function () {
        return vm.title;
    }, doSomething);
    
    function doSomething() {
    }
    }
    
    <!-- recommended -->
    <input type="text" ng-model="vm.title" ng-change="vm.doSomething()"/>
    
    /* recommended */
    function SomeController() {
      var vm = this;
      vm.doSomething = doSomething;
    
      function doSomething() {
      }
    }
    

Do you document the $watch inside the directive using controllerAs? Can you recommend a link or resource?

anyone interested in making a PR ?

cleanup my old issues

Was this page helpful?
0 / 5 - 0 ratings