DRiFTy
DRiFTy

Reputation: 11369

Communication between multi-layered directives in Angular

I'm creating a few directives that will make up a single "screen" in my app. To create this new screen you would write it like this:

<screen title="Test Title">
    <side-menu align="left">
        <menu-item>Test One</menu-item>
        <menu-item selected="true">Test Two</menu-item>
        <menu-item disabled="true">Test Three</menu-item>
    </side-menu>

    <content animation="fade">
        <view>Content for menu option 1</view>
        <view>Content for menu option 2</view>
        <view>Content for menu option 3</view>          
    </content>
</screen>

Each <menu-item> will display one of the "views" inside of the <content> tag. It works like tabs. I've got this set up by keeping track of each <view> inside of the <content> directive in an array when they are linked. Same for <menu-item>.

My question is, now that I've got this set up, what is the best way to communicate between the <side-menu> directive and the <content> directive to hide and show the correct view when clicked? Should I use events, a common service to hold state, or is there a way I can maybe access the controller inside of the <screen> directive from the <view> and <menu-item> directives, and hold the data/state there? From my understanding I can only access the parent controller from a child directive, but not the "grand parent" controller if you will, unless I use some sort of pass-through.

I plan to have a few more components on this "screen" that will need to communicate as well so I'm hoping to determine the "correct" way to do this before I continue, or at least get some feedback and other ideas.

If any of that is confusing, I'd be happy to provide more information.

Upvotes: 3

Views: 681

Answers (1)

DRiFTy
DRiFTy

Reputation: 11369

So after a bit of digging, I've learned that you can pass an array to the require property of a directive.

You can use this to find parent controllers, and grandparent controllers... etc. Previously each of my directives would have one require value such as: require: '^sideMenu' for the menuItem directive.

Now I can require the sideMenu and screen controllers into the menuItem directive by passing an array:

require: ['^screen', '^sideMenu']

Now in the link function of my menuItem directive, I can access these controllers this way:

link: function(scope, element, attrs, controllers) {
    var screenCtrl = controllers[0];
    var sideMenuCtrl = controllers[1];
}

Notice the controllers property is now an array of the controllers that I required, and are accessed by index. Although I feel as though my directives are little more tightly coupled now, I do like it better than using events/services.

I'm explaining all of this, because no where in the Angular docs does it mention this.

Upvotes: 4

Related Questions