0

If you have a directive that you're using multiple times on a page how can 1 directive communicate with another?

I'm trying to chain directives together in a parent child relationship. When directive A is clicked i want to filter Directive B to only have the children of the selected item in Directive A. In this case there may be infinite number of directives and relationships on the page.

Normally i would have Directive A call a filter method on each of it's children, and each child calls it's child to continue filtering down the hierarchy.

But i can't figure out if calling methods from 1 directive to another is possibe.

Thanks

m59
  • 43,214
  • 14
  • 119
  • 136
jadent
  • 3,674
  • 5
  • 27
  • 32

2 Answers2

1

It sounds like you are looking for a directive controller. You can use the require: parameter of a directive to pull in another directive's controller. It looks like this:

app.directive('foo', function() {
  return {
    restrict: 'A',
    controller: function() {
        this.qux = function() {
          console.log("I'm from foo!");
        };
    },
    link: function(scope, element, attrs) {

    }
  };
});

app.directive('bar', function() {
    return {
        restrict: 'A',
        require: '^foo',
        link: function(scope, element, attrs, foo) {
            foo.qux();
        }
    };
});

From the angular docs, here are the symbols you can use with require and what they do.

(no prefix) - Locate the required controller on the current element.
? - Attempt to locate the required controller, or return null if not found.
^ - Locate the required controller by searching the element's parents.
?^ - Attempt to locate the required controller by searching the element's parents, or return null if not found.

Here's a jsbin of my example. http://jsbin.com/aLikEF/1/edit

Another option that may work for what you need is to have a service that each directive sets up a watch on and can manipulate. For example, directive1 may watch a property in the service and respond to changes and also setup a button that can change that property. Then, directive2 can also watch and change the service, and they will respond to one another however you set that up. If you need a jsbin of that also, just let me know.

I hope this helps!

m59
  • 43,214
  • 14
  • 119
  • 136
  • Thanks so much. In this case we are reusing the same directive for each table so the require will not work (i don't think?). We need to tell the table which tables are it's children through a variable and the controller would need to find the childrens controllers dynamically through some type of id (like an html element id). Is that possible? – jadent Aug 20 '13 at 13:56
  • Hmm. You can find scopes that way, very easily. This should do it `var myScope = angular.element('#myElement').scope()`. I really am not quite sure what you're doing here. It sounds pretty messy. Another thought that sounds relevant to me is that you can use the directive's factory - the area here: `.directive('myDirective', function() { //this area!! return {` for something like an object or array that each run of the directive can see, if there's some shared information in each run, it could be added to the array or object for others to use. – m59 Aug 20 '13 at 14:08
  • @jadent If any of this is helpful, I'd appreciate the upvote/answer accept :) I see someone else already ripped off half of my response and used it for their answer. Also, see here for the traditional use of services to update $scope properties together. http://stackoverflow.com/questions/18668239/controllers-not-talking-to-each-other-via-service-in-angular-js/18668305#18668305 – m59 Sep 07 '13 at 16:20
0

You could try putting all of the data into a service that the directives can each reference.

Something like:

app.factory('selectedStuffService', function(){
    var allItems = [];
    var selectedItems = [];

    function addSelectedItem(item){
         selectedItems.push(item);
    }

    return {
        allItems: allItems,
        selectedItems: selectedItems,
        addSelectedItem: addSelectedItem
    }
}

Interactions in directive A change the values in the selectedItems array and directive B can bind to it. You can easily add other methods to the service to filter/manipulate the items as needed and any directive that uses the service should be able to update based on changes made by other directives.

Ian Muir
  • 911
  • 1
  • 9
  • 10