1

I am having a hard time understanding why the code in my directive won't stop running even after I have changed states and the dom element I am restricting the directive to is no longer in an available view. In the below code example, if I start at the home page, the document.addEventListener function will not run on mouse down, which is what I would expect. Then when I get the the our_purpose state, where the div with a class of "test" resides, the event fires on click as expected. However, when I navigate back to the home state, the event listener still persists.

How do I make it so all the code that lives within my test directive can be removed and no longer work ... Is there a way to restart everything from the directive so that it no longer exists until you are in that view?

This is a simplified version of my working code, but there is a lot of functionality in the real directive that causes issues when you are in the other state.

var app = angular.module('app', ['ui.router']);

app.directive("test", function() {
    return {
        scope: true,
        transclude: false,
        controller: 'OurPurposeCtrl',
        restrict:"C",
        link:function( scope, elem, attr) {
            function testThis() {
                console.log("still running the directive");
            }
            function init() {
               document.addEventListener( 'mousedown', testThis, false               );
            }
            init();

        }
    }
});

app.config(['$stateProvider','$urlRouterProvider', 
    function($stateProvider, $urlRouterProvider) {
        $stateProvider
            .state('home', {
                url: '/',
                controller: 'landing',
                templateUrl: 'views/landing.html'
            })

            .state('our_purpose', {
                controller: 'OurPurposeCtrl',
                url: '/our-purpose',
                templateUrl: 'views/our-purpose.html'

            })
    }
]);
Starfs
  • 412
  • 1
  • 5
  • 18
  • You are not removing event listener and that does not happen automatically - have a look here: http://stackoverflow.com/a/27016855/5131537 – JanisP Jul 21 '16 at 23:32

1 Answers1

2

You are attaching listener to document and it never gets destroyed so listener doesn't either

Remove event listener in destroy event of the scope using scope.$on('$destroy', function)

app.directive("test", function($document) {
    return {
        scope: true,
        transclude: false,
        controller: 'OurPurposeCtrl',
        restrict:"C",
        link:function( scope, elem, attr) {
            function testThis() {
                console.log("still running the directive");
            }
            function init() {
               $document.bind( 'mousedown', testThis );
            }
            init();

            scope.$on('$destroy', function(){
               $document.unbind( 'mousedown', testThis );
               console.log('Mousedown listener should be gone');
            });

        }
    }
});
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Yep, you are correct sir. As a side note for my particular instance I had to put this in the destroy function. document.removeEvenLtistener( 'mousedown', testThis ); I'm guessing this is a less angular approach? – Starfs Jul 22 '16 at 13:49
  • right, I used [angular.element](https://docs.angularjs.org/api/ng/function/angular.element) which is a subset of jQuery methods but has no jQuery dependency. Shorter to write – charlietfl Jul 22 '16 at 14:22