1

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

2 Answers 2

3

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
          }
      }
  })
Sign up to request clarification or add additional context in comments.

2 Comments

or extend scope (scope: true)
You're right. Forgot to isolate directive scope. Thanks
2
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
      }
  }
})

Comments

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.