AngularJs directive: call method from parent scope within template

19,130

One way would be to call the functions using $parent.

<button ng-show="editModel" ng-click="$parent.cancelProfile(); editModel=false">b3</button>

Demo

Another way (and probably the better way), is to configure your directive's isolated scope to contain references to those controller functions:

app.directive('editButton', function() {
  return {
    restrict: 'E',
    templateUrl: 'editbutton.tpl.html',
    scope: {
      editModel: '=ngEdit',
      updateProfile: '&',
      cancelProfile: '&'
    }
  };
});

Then you pass the functions in via HTML:

<edit-button ng-edit="editing.section1" update-profile='updateProfile()' cancel-profile='cancelProfile()'></edit-button>

Demo

Share:
19,130
Will Durney
Author by

Will Durney

Updated on June 26, 2022

Comments

  • Will Durney
    Will Durney almost 2 years

    I'm pretty new to Angular directives, and I'm having a lot of trouble getting this to do what I want. Here's the basics of what I have:

    Controller:

    controller('profileCtrl', function($scope) {
      $scope.editing = {
        'section1': false,
        'section2': false
      }
      $scope.updateProfile = function() {};
      $scope.cancelProfile = function() {};
    });
    

    Directive:

    directive('editButton', function() {
      return {
        restrict: 'E',
        templateUrl: 'editbutton.tpl.html',
        scope: {
          editModel: '=ngEdit'
        }
      };
    });
    

    Template (editbutton.tpl.html):

    <button
      ng-show="!editModel"
      ng-click="editModel=true"></button>
    <button
      ng-show="editModel"
      ng-click="updateProfile(); editModel=false"></button>
    <button
      ng-show="editModel"
      ng-click="cancelProfile(); editModel=false"></button>
    

    HTML:

    <edit-button ng-edit="editing.section1"></edit-button>
    

    If it's not clear, I want the <edit-button> tag to contain with three different buttons, each interacting with whatever scope property is passed into ng-edit. When clicked, they should change that property then call the appropriate scope method.

    The way it is now, clicking the buttons correctly changes the values of $scope.editing, but the updateProfile and cancelProfile methods don't work. I may be way off base on how to use directives properly, but I'm having trouble finding an example online to help me accomplish what I'm trying to do. Any help would be appreciated.

  • Will Durney
    Will Durney almost 10 years
    Great, thanks. I'm inclined to use your first example, since the two methods will always be the same across directives and it will reduce extraneous html. What makes you say that the second way is the "better way?"
  • Jerrad
    Jerrad almost 10 years
    @futurityverb, The second method is more general. If you want an instance of the directive with slightly different behavior, you can just pass in a different method that should be called. Also, if you start nesting your directive inside other directives, $parent may no longer refer to the controller scope, but some other intermediary scope.
  • Alex McCabe
    Alex McCabe about 8 years
    Pushed me in the right direction, but what if I want to pass arguments to the methods using your second example?
  • Jerrad
    Jerrad about 8 years
    Pass your argument in as an object. Something like this: update-profile='updateProfile({message: testMessage})'.