Explain Codes LogoExplain Codes Logo

Working with $scope.$emit and $scope.$on

javascript
event-driven-programming
angularjs
best-practices
Nikita BarsukovbyNikita Barsukov·Sep 10, 2024
TLDR

To create a linkage between controllers in AngularJS, unleash an event with $scope.$emit and capture it back with $scope.$on. Send the event upwards to the parental scopes using $scope.$emit and harness it with $scope.$on. Let's get this done:

// Child controller // Hypothetically throwing a ball upwards (who does that?) $scope.$emit('event', { data: 'Up!' }); // Parent controller // The ever-vigilant parent is always there to catch $scope.$on('event', function(event, args) { console.log(args.data); // Logs 'Up!', just like our ball });

Warning: Prevent the memory from turning into Swiss cheese by exterminating listeners with the $scope.$on return function when the scope is dismantled:

var offEvent = $scope.$on('event', function(event, args) { /* ... */ }); // Imagine this as the terminator of event listeners (I'll be back) $scope.$on('$destroy', offEvent); // This is where he says his catchphrase.

$rootScope: For those harder to reach places

For scenarios where the controllers don't exactly see eye-to-eye (i.e., they don't share a parent-child bond), $rootScope steps in like gossip. Use $rootScope.$broadcast or $rootScope.$emit to kick-start the chattering.

// Controllers sitting on different branches of the family tree // Initiate a global gossip $rootScope.$broadcast('globalEvent', { data: 'Broadcasted globally!' }); // Another controller vigilant for gossip (aren't we all?) $rootScope.$on('globalEvent', function(event, args) { console.log(args.data); // Logs 'Broadcasted globally!', just like our gossip });

The service key: Your trusted vault

Sometimes, events behave like a lazy runner, taking their time to ferry data between controllers. How about a vault (a.k.a service) that holds on to the data? Let's see how that's done.

app.service('SharedService', function() { var sharedData = {}; // Your vault return { setData: function(data) { sharedData = data; // Secure your valuables here }, getData: function() { return sharedData; // Safely retrieve them when needed } }; });

Performance: Ration your broadcasts

Be cautious with $rootScope.$broadcast, as it loves to shout out to all scopes. Let's just say that can lead to a performance hangover. Use it sparingly and look at alternatives like services or direct method calls.

Mastering propagation

An event $emitted is like a homeward-bound pigeon, charting upwards through the scope hierarchy, whereas $broadcast events are quite the explorer; they venture downwards to all child scopes.

// Parent scope unleashing an event for the child scopes $scope.$broadcast('downEvent', { data: 'Downward dog!' }); //Not a yoga reference!

Tidy event listeners

Listeners tied to $scope.$on are auto-cleaned after the scope bows out. However, $rootScope listeners need a maid. Use $on('$destroy', ...) as your cleaning service.

var globalOff = $rootScope.$on('globalEvent', function() {}); $scope.$on('$destroy', function() { globalOff(); // Pay your cleaning bills to avoid memory dirt });

Communication: Keep it simple

To avoid ending up with an event type buffet, emit a generic message with $emit and let the parent controller be the decider. It handles specific actions and keeps things neat.