4

I need to get parent's controller, so my directive has a require property, as follows:

module.directive('tag', function () {
    return {
        require: '?^tag',
        restrict: 'E',
        controller: function () {
            this.payload = getPayload();
        },
        link: function (scope, element, attrs, ctrl) {
            usePayload(ctrl.payload);
        }
    };
});

However the ctrl parameter of the link function returns the controller of the current directive, not the parent's one. AngularJS documentation is clear about this:

?^ - Attempt to locate the required controller by searching the element's parents, or return null if not found.

What am I doing wrong?

4
  • 1
    require: '?^parent' or assign directive's controller to the name of the parent controller or leave off the directive's controller all together and ctrl in the link parameters will default to the parent. Commented Oct 11, 2013 at 14:10
  • Have a look at this video by John Lindquist which explains communicating between nested directives pretty well. Commented Oct 11, 2013 at 14:14
  • @m.e.conroy: I have to use the same name in require. If no controller is declared, ctrl defaults to undefined. Commented Oct 11, 2013 at 14:36
  • @JonathanPalumbo: That example is not recursive meaning the directive names are different. Commented Oct 11, 2013 at 14:39

1 Answer 1

10

Either the docs or the code are misleading here... require with ^ looks at the current element and then all parent, using the inheritedData method (see https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L942). So you won't be able to require a directive with the same name from a parent using this approach.

When I've had this issue in the past I've looked at the form directive which needs to do what you are asking. Its controller method grabs the parent like so (https://github.com/angular/angular.js/blob/master/src/ng/directive/form.js#L39):

controller: function($element) {
    var parentForm = $element.parent().controller('form');
}

Taking this, you should be able to call element.parent().controller('tag') to find the parent controller either in the controller or postLink methods.

Sign up to request clarification or add additional context in comments.

3 Comments

This works, thanks! My only concern is that the controller() method is not exposed in their API, so not intended for public use and may be subject to change.
Docs can be found buried in those for angular.element: docs.angularjs.org/api/angular.element. This is definitely documented in the unstable branches but I haven't checked stable.
This is so helpful. Thanks, i wanted to make an element that could act as a container for itself, so, this is perfect. Also, I've read it's not a good idea to pass the element to the controller so you could always work with the element in the link function

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.