ianaya89 ianaya89 - 6 months ago 14
AngularJS Question

Calling directive's methods from parent controller in AngularJS

I am using AngularJS with the alias controllers pattern. I can't access (or I don't know how to) directive methods from a parent controller.

I have a function inside my controller that should call a directive method but this directive method is not available inside the

this
controller value.

This is what I have. What I am doing wrong?

JS

angular.module('myApp', []).

controller('MyCtrl', function(){
this.text = 'Controller text';

this.dirText = 'Directive text';

this.click = function(){
this.changeText();
}
})

.directive('myDir', function(){
return {
restrict: 'E',
scope: {
text: '='
},
link: function(scope, element, attrs){
scope.changeText = function(){
scope.text = 'New directive text';
};
},
template: '<h2>{{text}}</h2>'
};
});


HTML

<div ng-app="myApp">
<div ng-controller="MyCtrl as ctrl">
<h1>{{ctrl.text}}</h1>
<my-dir text="ctrl.dirText"></my-dir>
<button ng-click="ctrl.click()">Change Directive Text</button>
</div>
</div>


Here a codepen with the code.

Answer

If you want to strictly use isolated scope inside directive then the directive method can be only called by using angular events such as $broadcast & $emit

In your case you need to use $broadcast to send event to entire $rootScope

You Code will become like this.

Working Code Pen

HTML

<div ng-app="myApp">
  <div ng-controller="MyCtrl as ctrl">
    <h1>{{ctrl.text}}</h1>
    <my-dir text="ctrl.dirText"></my-dir>
    <button ng-click="ctrl.click()">Change Directive Text</button>
  </div>
</div>

CODE

angular.module('myApp', []).

controller('MyCtrl', function($rootScope){
  var that = this;

  this.text = 'Controller text';

  this.dirText = 'Directive text';

  this.click = function(){
      $rootScope.$broadcast('changeText',{});
  }
}).

directive('myDir', function(){
  return {
     restrict: 'E',
     scope: {
       text: '='
     },
     link: function(scope, element, attrs){
       scope.changeText = function(){
         scope.text = 'New directive text';
       };
         scope.$on('changeText',function(event, data){
             scope.changeText()
         });
     },
     template: '<h2>{{text}}</h2>'
  };
});

Instead of calling method of child scope, you need to broadcast event and that will listen by the directive scope & it will fire changeText method after listening that event.

NOTE

Using service / factory would be better approach.

This would be hopefully help you. Thanks.

Comments