Chris Hermut
Chris Hermut

Reputation: 1758

Using directives with controllerAs

As far as I know using controller property on 'Directive Definition Object' will create a separate instance of that controller everytime a given directive is linked?

Now playing with controllerAs patters I can see that when each of directives is being compiled the controller factory function is being triggered giving a different result for this.data.hello method.

But in my view I'm getting last instance of that controller. Why is that? What am I missing?

js

angular.module('app', [])
  .controller('customCtrl', function () {
      console.log('controller');

      this.data = {
          hello: Math.floor(Math.random() * 200 + 1)
      };
  })
  .directive('customDrv', function () {
      var linkFn = function (scope, element, attrs, ctrl) {
          console.log('link');
          console.log(ctrl.data.hello);
      };

      return {
          templateUrl: 'Home/CustomDrv',
          restrict: 'E',
          controller: 'customCtrl',
          controllerAs: 'vm',
          compile: function (element, attrs) {
              console.log('compile');

              return linkFn
          }
      }
  })

Html

<custom-drv></custom-drv>
<custom-drv></custom-drv>
<custom-drv></custom-drv>
<custom-drv></custom-drv>

Plunker: https://plnkr.co/edit/HII9a7Ff6ryXuz6Fgzr6

Upvotes: 1

Views: 60

Answers (2)

Sumit Deshpande
Sumit Deshpande

Reputation: 2155

To get the different result for this.data.hello method create isolated scope as -

angular.module('app', [])
  .controller('customCtrl', function () {
      //console.log('controller');

      this.data = {
          hello: Math.floor(Math.random() * 200 + 1)
      };
  })
  .directive('customDrv', function () {
      var linkFn = function (scope, element, attrs, ctrl) {
          //console.log('link');
          console.log(ctrl.data.hello);
      };

      return {
          template: '<h1>{{vm.data.hello}}</h1>',
          restrict: 'E',
          scope: {},
          controller: 'customCtrl',
          controllerAs: 'vm',
          compile: function (element, attrs) {
              //console.log('compile');

              return linkFn
          }
      }
  })

Upvotes: 3

Muli Yulzary
Muli Yulzary

Reputation: 2569

this.data = {
      hello: Math.floor(Math.random() * 200 + 1)
  }

Sets data.hello only one time (on controller load). If you want a different outcome everytime you'd say:

this.data = {
      hello: function(){
        return Math.floor(Math.random() * 200 + 1);
      }
  }

And invoke it with

ctrl.data.hello()

Working plunkr

However you probably want to pass hello function through the binding and not access it directly from the directive (better practice):

Markup:

<custom-drv hello="hello"></custom-drv>

Directive:

.directive('customDrv', function () {
  var linkFn = function (scope, element, attrs, ctrl) {
      console.log('link');
      console.log(ctrl.hello);
  };

  return {
      template: '<h1>{{vm.hello()}}</h1>',
      restrict: 'E',
      scope: {
       hello: '&' //represent function binding
      }
      controller: 'customCtrl',
      controllerAs: 'vm',
      compile: function (element, attrs) {
          console.log('compile');

          return linkFn
      }
  }
})

Upvotes: 2

Related Questions