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 outHow 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 $destroy
ing 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