Rob Fyffe
Rob Fyffe

Reputation: 729

In Angular 1.x how can I access controller methods from a custom directive?

I am currently trying to figure out the best way to access two controller methods from within my custom directive. My current code looks like so:

Parent Component Template (navMenus.html):

<menu-toggle section="navItem" ng-if="navItem.type === 'toggle'"></menu-toggle>

Parent Component Controller (navMenus.controller.js):

...
isOpen(section) {
  return this.NavMenusFactory.isSectionSelected(section);
}

toggleOpen(section) {
  this.NavMenusFactory.toggleSelectSection(section);
}
...

Directive Template (menuToggle.html):

<md-button class="md-button-toggle" ng-click="vm.toggle()">
    {{ section.text | translate }}
</md-button>

<ul ng-show="vm.isOpen()" class="menu-toggle-list">
  <li ng-repeat="subItem in section.subItems">
    {{ subItem.text | translate }}
  <menu-link section="subItem"></menu-link>
  </li>
</ul>

Directive (menuToggle.directive.js):

...
return {
  restrict: 'AE',
  template,
  replace: true,
  scope: {
   section: '=',
  },
  link(scope, element) {
    $timeout(() => {
      const $element = element;


      scope.vm.toggle = function () {
        console.log(scope.$parent.isOpen());
      };

      scope.isOpen = function () {
       return $element.isOpen(scope.section);
      };

      scope.toggle = function () {
       $element.toggleOpen(scope.section);
      };

    });
  }
}

How can I access these methods?

Upvotes: 1

Views: 77

Answers (2)

Rohan Kangale
Rohan Kangale

Reputation: 971

Since there is scope in your directive, you have created an isolated scope. So in order order to access the controller's function you can make use of events

  • Inside directive, create an $emit event, on the click event:

    scope.toggle = function toggle (){
    
        scope.$emit('EVENT_NAME', { data: true }) // here data is optional
    
    }
    
  • In controller, you can perform action as:

    $scope.$on('EVENT_NAME', function(event, data){
    
         // here you can call the controller's method
    
    })
    

Upvotes: 1

Nikhil Mohanan
Nikhil Mohanan

Reputation: 1260

This is the best way i know, to call a controller function from directive.

/* Directive template */
<md-button class="md-button-toggle" ng-click="vm.toggle()">
    {{ section.text | translate }}
</md-button>

<ul ng-show="isOpen()" class="menu-toggle-list">
  <li ng-repeat="subItem in section.subItems">
    {{ subItem.text | translate }}
  <menu-link section="subItem"></menu-link>
  </li>
</ul>



/* Directive Code */
...
return {
  restrict: 'AE',
  template,
  replace: true,
  scope: {
   section: '=',
   isOpen: '&'
  },
  link(scope, element) {
    $timeout(() => {
      const $element = element;


      scope.vm.toggle = function () {
        console.log(scope.$parent.isOpen());
      };

      scope.isOpen = function () {
       return $element.isOpen(scope.section);
      };

      scope.toggle = function () {
       $element.toggleOpen(scope.section);
      };

    });
  }
}

/* in your view, you can call controller fn */

<menu-toggle section="navItem" is-open="isOpen()" ng-if="navItem.type === 'toggle'"></menu-toggle>

Upvotes: 0

Related Questions