1

I have a directive that contains in his controller a watcher like:

$rootScope.$on('broad1', (event, args) => {
            doSomething()
});

Then, I reload (with $state.go) a part of my page that contains my directive. And unfortunately, even if my directive is reinit and of course, not duplicated, a new watcher is created and added in my rootscope. ( I already know that when watcher are attached to rootscope, isn't destroyed whereas the directive is removed from DOM)

So, when I broadcast 'broad1' the watchers are executed n times (corresponding to n previous reloads). WHY?

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Mika
  • 13
  • 2

2 Answers2

1

When using the AngularJS event bus in directives, events listeners should be placed on local scope. Events should be broadcast from $rootScope:

app.directive("myDirective", function() {
    return {
        link: postLink,
    };
    function postLink(scope,elem,attrs) {
        scope.$on('broad1', (event, args) => {
            doSomething()
        });
        scope.broadcast = function(data) {
            scope.$root.$broadcast("broad1", data);
        };
    };
})

When the scope is destroyed the event listener will automatically be removed.

For more information, see


Update

Keep in mind the the AngularJS event bus is inefficient and obsolete. Whenever possible use more direct ways to communicate events to their recipients.

From the Docs:

Only use .$broadcast() and .$on() for atomic events

Events that are relevant globally across the entire app (such as a user authenticating or the app closing). If you want events specific to modules, services or widgets you should consider Services, Directive Controllers, or 3rd Party Libs

  • Injecting services and calling methods directly is also useful for direct communication
  • Directives are able to directly communicate with each other through directive-controllers

AngularJS Wiki - Best Practices

See also,

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • If you don't use $broadcast and that you want to edit something stored in the scope of parent directives, angularjs won't be able to detect it unless you explicitely call $scope.$apply on the specific directive. $on and $broadcast are working even if this is not the perfect way to handle it, but it's the way to do it in angularjs 1.X. – Pierre Emmanuel Lallemant Apr 25 '19 at 19:13
  • To communicate events from child directive to parent controller, there are several alternatives to the scope event bus that are more efficient. To make migration to Angular 2+ easier, the AngularJS team introduced components. For more information, see [AngularJS Developer Guide - Component-based application architecture](https://docs.angularjs.org/guide/component#component-based-application-architecture). See also [AngularJS 1.5+ Components do not support Watchers, what is the work around?](https://stackoverflow.com/a/35535336/5535245). – georgeawg Apr 25 '19 at 19:38
0

thank you for your reactivity and insight, I've fixed it by using the $scope.on[...] and $rootscope.broadcast[...]. In other hand the "service way" was a good one too.

Have a nice day.

Mika
  • 13
  • 2