0

I have a page with two directives. I need to invoke a function in one directive from the other. I have added the function to the $element object of the first directive and used jQuery to invoke it from the other. Is this the right approach or should I be using a context object shared by both directives?

//inside directive 1 link fn
$element[0].foo = function(){
console.log("test");
}

...
//inside directive 2 link fn
$('.className').foo()

The two directives are elements on a page with a shared controller. Each has an isolated scope. This seems to work well. Are there any reasons why I should not do this?

OLahav
  • 1
  • 2
  • You should probably post this to the http://codereview.stackexchange.com/ – jehna1 May 24 '16 at 20:53
  • 1
    @jehna1 this would be off-topic on Code Review as the code posted in the question clearly doesn't compile/work as it is stub code. See [A guide to Code Review for Stack Overflow users](http://meta.codereview.stackexchange.com/a/5778/42632) – Phrancis May 24 '16 at 20:56
  • Not having the full code, I assumed the "Is this the right approach" referred to the not-displayed-here code actually working. If the code is broken, then ofc stackoverflow is the way to go. – jehna1 May 24 '16 at 20:59
  • 1
    Please provide all relevant code structure. If one directive is child of the other can `require` the parent controller in the child – charlietfl May 24 '16 at 21:03
  • If you're not using isolate scopes, you can make one of your directives inject the function (e.g. $foo) to the scope and have your other directive use an attribute to use that scope method (e.g. do-foo="$foo()"). – Ates Goral May 24 '16 at 21:15

2 Answers2

0

are the 2 directives sharing the same controller? If so, you could call a function on the controller from one directive which would "notify" the other. Or, you could use events, check this answer here

Community
  • 1
  • 1
nuway
  • 2,324
  • 4
  • 27
  • 48
-1

This is not the way you should do it. Try to avoid using $element, it does DOM manipulations which are slow and Angular takes care of by itself. To invoke a function in directiveB, triggered from directiveA, you better make a service.

angular.service('Communication', function () {
  var _listeners = [];

  return {
    addListener: function (callback) {
      _listeners.push(callback);
    },
    removeListener: function () {/* Clean up */},
    invokeListeners: function (data) {
      _listeners.forEach(function (listener) {
        listener(data);
      });
    }
  }
});

angular.directive('directiveB', ['Communication', function (Communication) {
  return {
    restrict: 'AE',
    scope: {},
    controller: directiveB
  };

  function directiveB (scope, element, attrs) {
    Communication.addEventListener(function (data) { /* Do stuff with data */  });
  }
}]);

angular.directive('directiveA', ['Communication', function (Communication) {
  return {
    restrict: 'AE',
    scope: {},
    controller: directiveA
  };

  function directiveA (scope, element, attrs) {
    // trigger event in directive B
    Communication.invokeListeners('test');
  }
}]);
dejakob
  • 2,062
  • 14
  • 21