0

I've got a directive that needs to do something every now and then, let's say it has to count something. If I use the basic syntax with $scope to bind the count function, it works just fine. but when we switch to the controller as syntax it doesn't bind the function. Here is a working plunker: https://plnkr.co/edit/C2wVaeOm63SLnXBG?open=lib%2Fscript.js&deferRun=1&preview

JS

angular
  .module('plunker', [])
  .controller('MainCtrl', function ($scope) {
    var vm = this;
    vm.name = 'Plunker';
    setInterval(function () {
      $scope.count();
    }, 1000);
    setInterval(function () {
      $scope.count2();
    }, 1000);
    setInterval(function () {
      $scope.count3();
    }, 1000);
  })
  .directive('test', function () {
    return {
      scope: {
        count: '=',
      },
      controller: function ($scope) {
        $scope.i = 0;
        $scope.count = function () {
          $scope.i++;
          console.log($scope.i);
        };
      },
    };
  })
  //with bindToController
  .directive('test2', function () {
    return {
      scope: {
        count: '=',
      },
      bindToController: true,
      controller: function ($scope) {
        var vm = this;
        vm.i = 0;
        vm.count = function () {
          vm.i++;
          console.log(vm.i);
        };
      },
    };
  })
  //with bindToController - the new way
  .directive('test3', function () {
    return {
      scope: true,
      bindToController: {
        count: '=',
      },
      controller: function ($scope) {
        var vm = this;
        vm.i = 0;
        vm.count = function () {
          vm.i++;
          console.log(vm.i);
        };
      },
    };
   });

HTML

<body ng-app="plunker" ng-cloak>
    <div ng-controller="MainCtrl as vm">
      <h1>Hello {{vm.name}}</h1>
      <test count="count"></test>
      <test2 count="count2"></test>
      <test3 count="count3"></test>
    </div>
  </body>

2 Answers 2

1

If you are using bindToController syntax, then you should declare your directive count function in directive link function, because binding is happening after directive controller initialisation.

Your modified example here:

  //with bindToController
  .directive('test2', function () {
    return {
      scope: {
        count: '=',
      },
      bindToController: true,
      controller: function ($scope) {
        var vm = this;
        vm.i = 0;
      },
      link:function($scope,$element,$attr,ctrl){
        ctrl.count = function () {
          ctrl.i++;
          console.log('test2',ctrl.i);
        };
      }
    };
  })

Or you can check my modified plunker here: https://plnkr.co/edit/TKTtObbDTcFFC9SS?open=lib%2Fscript.js&deferRun=1

Sign up to request clarification or add additional context in comments.

1 Comment

it works just fine. it's bad practice to encapsulate the count() function like this? plnkr.co/edit/…
0
angular
  .module('plunker', [])
  .controller('MainCtrl', function ($scope, $interval) {
    var vm = this;
    vm.name = 'Plunker';
    ̶s̶e̶t̶I̶n̶t̶e̶r̶v̶a̶l̶(̶f̶u̶n̶c̶t̶i̶o̶n̶ ̶(̶)̶ ̶{̶
    $interval(function () {
      $scope.count();
    }, 1000);

Use the $interval service.

AngularJS modifies the normal JavaScript flow by providing its own event processing loop. This splits the JavaScript into classical and AngularJS execution context. Only operations which are applied in the AngularJS execution context will benefit from AngularJS data-binding, exception handling, property watching, etc.

For more information, see

1 Comment

thanks, i used setInterval only for example. Anyway, changed setInterval to $interval and we have the same outcome:plnkr.co/edit/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.