14

I'm broadcasting an event from my navbar controller to another controller, but if I initialize the controller multiple times (when I'm going front and back through the application) the function that executes on my $on event runs multiple times because it's registered multiple times.

$rootScope.$on('submitBookingDialog', function(){
    submitBookingDialog();
});

How can I prevent the submitBookingDialog() to happen more than once?

I found a solution, but I don't know if it's ideal.

3

5 Answers 5

29

First of all, do you need to send the event on the $rootScope? If not, then you could just register your event handler on the $scope. The event handler will be destroyed whenever your controller scope is destroyed. You would then send the event via $scope.$emit or $scope.$broadcast depending on your controller hierarchy.

That being said, all you need to do to destroy your event listener is call the deregistration function that is returned when registering the listener:

var offSubmitBookingDialog = $rootScope.$on('submitBookingDialog', function(){
    submitBookingDialog();
});

$scope.$on('$destroy', function() {
    // Call the deregistration function when the scope is destroyed
    offSubmitBookingDialog();
});
Sign up to request clarification or add additional context in comments.

Comments

18

This seems to do it for me:

var removeListener = $rootScope.$on('submitBookingDialog', function(){
    submitBookingDialog();

    // Remove listener
    removeListener();
});

2 Comments

Thank you for this correct answer. The $on operation returns the function signature, therefore you just call it when appropriate to remove it.
Thanks. This is the way to do it. You can find a similar answer here
6

For posterity I ended up doing this:

.run(function($rootScope) {
    $rootScope.once = function(e, func) {
        var unhook = this.$on(e, function() {
            unhook();
            func.apply(this, arguments);
        });
    };
})

Because I kept needing to do this in a few places this just ended up being cleaner.
With that on your app module you can now just call once instead of $on:

$rootScope.once('submitBookingDialog', function() {
    submitBookingDialog();
});

Comments

3

I ran into a similar situation, so I wrote a small library to make pub/sub stuff easier.

https://github.com/callmehiphop/hey

1 Comment

:D Glad you found it useful!
2

Maybe you shoud unsubscribe on controller destroy event

var removeSubmitBookingDialog = $rootScope.$on('submitBookingDialog',submitBookingDialog);
$scope.$on("$destroy", removeSubmitBookingDialog);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.