-1

Having a controller, MyCtrl:

class MyCtrl {
    constructor($scope, $rootScope, ...) {
        this.$scope = $scope;
        this.$rootScope = $rootScope;
        this.doThis = _debounce(this.resize.bind(this), 300);
        ...
    }
    $onInit() { ... }
    $onDestroy() { ... }
}

Inside $onInit is called $rootScope.$on. Like this one, is another controller with does the same operations but for a different type of page, let's say MyCtrl2. When I go to the second one from the first one, the first one keeps getting called because it is not destroyed. I solved this problem using the method described Prevent $rootScope.$on from calling function several times by adding a deregister. The $onInit now:

$onInit() {
    this.$rootScope.$on('toggleNav', () => {
        this.doThis();
    });
    this.deregisterDoThis = this.$rootScope.$on('listen', function() {
        this.$scope.doThis();
    });
    this.$rootScope.$on('$destroy', this.deregisterDoThis);
}

Now, if I go from the first controller's page to the page of the second, everything works fine. BUT, when I click for going back to the page of the first one, there is an error in the console saying:

 Uncaught TypeError: Cannot read property 'getAttribute' of null
    at $.t.default [as attr] (vendor.dll.js?aca3f637cd46c07f3280:135)
    at attachNotes (VM133106 chart-util.js:1016)
    at invokeFunc (debounce.js?e59c:95)
    at trailingEdge (debounce.js?e59c:144)
    at timerExpired (debounce.js?e59c:132)

Any ideas about this?

georgeawg
  • 48,608
  • 13
  • 72
  • 95
Leo Messi
  • 5,157
  • 14
  • 63
  • 125
  • You can use the return value of `$scope.$on` to deregister an event. Refer - https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$on – Aditya Bhave Sep 30 '19 at 09:37
  • sorry, I don't get it. – Leo Messi Sep 30 '19 at 10:10
  • You can try using `$stateChangeSuccess` event to re-bind the `$scope.$on` handler – Aditya Bhave Sep 30 '19 at 10:19
  • try : `this.deregisterDoThis = this.$rootScope.$on('listen', () => { this.$scope.doThis(); });` – anoop Sep 30 '19 at 10:23
  • @anoop any other difference than the original except that you are using ES6 syntax ? – Aditya Bhave Sep 30 '19 at 10:26
  • @AdityaBhave: it is important to keep the scope of `this` (can be done by ES6), else it will be null. Further to deregister the event `$destroy` should be enough, see [this thread](https://stackoverflow.com/questions/14898296/how-to-unsubscribe-to-a-broadcast-event-in-angularjs-how-to-remove-function-reg) – anoop Sep 30 '19 at 10:40
  • @anoop, looks like the same thing I did, I tried it anyway, the same error as result => run in in ctrl1 - works fine, go to ctrl2 - works fine, go back to ctrl1 - error – Leo Messi Sep 30 '19 at 11:08

1 Answers1

2

$rootScope.$on('$destroy') is never called because $rootScope is never destroyed.

$onInit() {
    this.deregisterToggleNav = this.$rootScope.$on('toggleNav', () => {
        this.doThis();
    });
    this.deregisterDoThis = this.$rootScope.$on('listen', ̶f̶u̶n̶c̶t̶i̶o̶n̶(̶)̶ () => {
        ̶t̶h̶i̶s̶.̶$̶s̶c̶o̶p̶e̶.̶d̶o̶T̶h̶i̶s̶(̶)̶;̶
        this.doThis();
    });
    ̶t̶h̶i̶s̶.̶$̶r̶o̶o̶t̶S̶c̶o̶p̶e̶.̶$̶o̶n̶(̶'̶$̶d̶e̶s̶t̶r̶o̶y̶'̶,̶ ̶t̶h̶i̶s̶.̶d̶e̶r̶e̶g̶i̶s̶t̶e̶r̶D̶o̶T̶h̶i̶s̶)̶;̶
}

Instead use the $onDestroy Life-cycle Hook:

$onDestroy() {
    this.deregisterToggleNav();
    this.deregisterDoThis();
}

For more information, see

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • it has the same behavior. shouldn't be made a change in $onDestroy maybe? like set deregisterDoThis() to null or false or something like that – Leo Messi Sep 30 '19 at 13:15