Reputation: 6657
In an AngularJS project we have a video
element that needs to toggle between playing and paused when the user hits Space. This might be a slightly naive implementation, but in a directive we've wired up a handler to the $document
click event to toggle the video. It looks like this:
var video = element.find('video')[0];
$document.on('keypress', function(evt){
if(evt.which === 32) {
// toggle video
video[video.paused ? 'play' : 'pause']();
}
});
This has worked as expected so far. Only problem is that the directive is hidden or shown using an ng-if
directive, but even after the the ng-if
expression evaluates to false
, the document click handler still holds onto the video reference. We discovered this when we still heard the video playing, even after it was no longer in the DOM.
I've created a Plnkr Example to demonstrate the issue. The video disappears after 2.5 seconds, but you'll notice that you can press Space to toggle the video state even after it is removed from the DOM by ng-if
.
For an answer, I'm looking for either:
1) A better, perhaps "more Angular" approach to solving this issue.
2) A way to detect that the video is no longer on the DOM so the reference can be deleted.
Thanks!
Upvotes: 1
Views: 260
Reputation: 2811
The angular way would be to add this to the link function:
scope.$on("$destroy", function () {
$document.off('keypress');
});
This is good practice in any directive event binding. Eventually (as I understand) the garbage collector will go through and clear out these events, but if you are making events on items in ng-repeat.... then you potentially have a memory leak.
Upvotes: 1