Custom Angular directive broadcasting an event but not for nested children?

I have created a harmonic directive in Angular that can be nested, so a harmonic can have child chords in it.

I want to broadcast an event when the accordion opens and closes so that other directives can listen to it (for example, the menu inside the accordion panel can reveal itself when it is open inside).

The point is, if inside the outer nested inner harmonic I don't want the event to be broadcast to the inner chord children, because the inner consonant was not broadcasting the open / close event.

Just in case this is pointless, in other words, an element inside a nested accordion should be able to listen to the broadcast of the open / closed accordion it is in, and not further away from the DOM tree.

Hope this is an easy solution.

Update: Demo added: http://jsfiddle.net/jonhobbs/xr1kLqba/

I obviously didn't understand $ broadcast and $ because the demo events are currently not working at all, but it should be clear what I am trying to do!

Edit: Obviously, all links to jsfiddle must be accompanied by code, so here are some of them.

var app = angular.module('app', []);

app.controller('MainCtrl', function($scope) {
  $scope.mainMenuOpen = true;
})

.directive('myPanel', function() {
  return {
    restrict: 'EA',
    scope: {
      isOpen: '=?'
    },
    link: function($scope, $element, $attrs) {  
      $element.find('> BUTTON').bind('click', function() {

        $scope.isOpen = !$scope.isOpen;
        if ($scope.isOpen) {
          $scope.$broadcast('panelOpened');
        }
      });
    }
  };
})

.directive('reactToPanelOpenClose', function() {
  return {
    restrict: 'EA',
    scope: {},
    link: function($scope, $element, $attrs) {
      $scope.$on('panelOpened', function() {

        alert("clicked");

        $element.css({ 'background-color': 'red' });
      });
    }
  };
});

      

+3


source to share


3 answers


The easiest way is to use the require

one you mentioned in the comments.

One way to solve this problem is to register child controllers (or even their callback functions) and then the parent can call on each child instead of broadcast.



It should be noted here that you need require: "?^^parent"

- value, make the request an optional and strict ancestor selector; for "^"

Angular will return self.

.directive("accordion", function(){
  return {
    require: ["accordion", "?^^accordion"],
    controller: function(){
       var children = [];
       this.registerChild = function(childCtrl){
          children.push(childCtrl);
       }

       this.handleNotification = function(){
          // do something when notification arrives from parent
       }

       this.notify = function(){
          angular.forEach(children, function(child){
            child.handleNotification();
          })
       }
    },
    link: function(scope, element, attrs, ctrls){
      var me = ctrls[0], parent = ctrls[1];

      if (parent){
         parent.registerChild(me);
      } 
    }
  }
})

      

+1


source


I am trying to work with angular context inside jQuery callback, so it doesn't work. The easiest way to solve your problem is the following piece of code:

angular.$externalBroadcast = function (element, event, data) {
    var scope = element.scope();
    scope.$apply(function () {
        scope.$broadcast(event, data);
    });
};

      

And apply this function inside the link function of the panel directive:



$scope.isOpen = !$scope.isOpen;                
if($scope.isOpen){
    angular.$externalBroadcast($element, 'panelOpened');
}

      

Take a look at this modified Fiddle .

+1


source


You can add a numeric value depth

or similar to your broadcast that defines the hierarchical depth from which the broadcast was sent. if the controller listener for directives has depth

of 1

above, it can execute. Otherwise it might just ignore the broadcast.

If it's unclear, I might as well add a small example, just let me know.

0


source







All Articles