Plnkr example build: http://plnkr.co/edit/gB7MtVOOHH0FBJYa6P8t?p=preview
Following the answer here, I created some $broadcast events to allow actions in the main $scope to close popovers in sub $scopes. However I want to make sure I clean up all my events and not have anything lingering that should not.
I have a popover directive, once the popover is activated I send out:
vs.$emit('popoverOpen');
Then in the main app module ($rootScope), I listen for it here:
vs.$on('popoverOpen',function(events,data) {
// if 'popoverOpen' is heard, then activate this function
// which on click $broadcasts out even 'bodyClick'
// but also destroy the 'popoverOpen' event
vs.bodyClick = function() {
$rootScope.$broadcast('bodyClick');
$rootScope.$$listenerCount.popoverOpen=[];
};
});
Back in the popover Directive, here is my bodyClick listener:
vs.$on('bodyClick', function() {
vs.searchPopoverDisplay = false;
$rootScope.$$listenerCount.bodyClick=[];
});
^ I also have code in there attempting to kill the bodyClick event, however to no avail :(
As you can see below, I've removed bodyClick and popoverOpen from the $$listenerCount (there was never anything in the $$listener object.
However the user is still able to access the vs.bodyClick() function in the main app rootScope, even though popoverOpen should have been removed.
So on first load:
bodyClick is never captured / transmittedbodyClick is activebodyClick event keeps getting sent out
How would you properly remove the events after the bodyClick event has been sent out to close the popover?
UPDATE I also tried this (https://github.com/toddmotto/angularjs-styleguide#publish-and-subscribe-events), but still the bodyClick event keeps getting sent out after the popover is closed and supposedly destroyed.
popoverDirective function still gets called:
vs.$on('bodyClick', function() {
console.log('bodyClick received ...');
console.log($rootScope.$$listener);
console.log($rootScope.$$listenerCount);
vs.searchPopoverDisplay = false;
var unbind = $rootScope.$on('popoverOpen', []);
vs.$on('$destroy', unbind);
// $rootScope.$$listenerCount.bodyClick=[];
});

A few notes about your plunkr:
$destroy. $destroy but attempting to
emit destroy, which isn't the same. Remove the $ from the
listener and you'll see the callback running.subController is a child of mainController destroying main destroys both and stops the button, along with everything else. This behavior is shown in this plunkr.So in order to get the pseudo-$destroy to ping, I changed it to listen on just destroy.
Then, instead of calling your unbind, which wouldn't work in this case as we aren't actually $destroying anything, I simply replaced the bodyClick function, as it is bound to the <body>.
$scope.$on('destroy', function() {
$scope.bodyClick = angular.noop();
});
This seems to have the desired effect. Updated Plunkr here.
Update: I discovered why it was indefinitely adding listeners...! The destroy listener was in the button callback. So each button press would add yet another callback. I moved the destroy listener outside of the popover listener. No more memory leaking!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With