codelord.net

Code, Angular, iOS and more by Aviv Ben-Yosef

AngularJS: Notifying about changes from services to controllers

| Comments

Once you write enough Angular code you (hopefully) start pushing off as much logic as you can from your controllers to services (note: I’m saying “services” as in the general concept, but technically these are usually factories).

Eventually you’ll stumble upon the need to have your services notify controllers about changes. You have a lot of options: passing callbacks from controllers to services, using $watch on shared data, promises, events, etc. A lot of us end up wondering what’s the best practice in this case?

In my opinion there’s one way that’s almost always better.

Pub-Sub using “hidden” events

Angular’s events mechanism ($on, $emit, $broadcast) is useful, but if you don’t use it just right it can quickly spiral out of hand. Also, causing memory leaks is remarkably easy. But, with right incantation we can use it to our advantage in quite a robust way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
angular.module('app').controller('TheCtrl', function($scope, NotifyingService) {
    // ... stuff ...
    NotifyingService.subscribe($scope, function somethingChanged() {
        // Handle notification
    });
});

angular.module('app').factory('NotifyingService', function($rootScope) {
    return {
        subscribe: function(scope, callback) {
            var handler = $rootScope.$on('notifying-service-event', callback);
            scope.$on('$destroy', handler);
        },

        notify: function() {
            $rootScope.$emit('notifying-service-event');
        }
    };
});

Win!

You can use this little snippet whenever you need to. It comes with these already bundled in:

  • It takes care of cleaning up after itself properly by listening for the $destroy event on the controller’s scope
  • It uses events only on the $rootScope using $emit which is more performant than using $broadcast (further reading if you’re interested)
  • It encapsulates the actual use of the events mechanism inside the service, which, IMO, makes for cleaner interfaces

Here’s a little jsfiddle that shows this in action.

“Maintaining AngularJS feels like Cobol 🤷…”

You want to do AngularJS the right way.
Yet every blog post you see makes it look like your codebase is obsolete. Components? Lifecycle hooks? Controllers are dead?

It would be great to work on a modern codebase again, but who has weeks for a rewrite?
Well, you can get your app back in shape, without pushing back all your deadlines! Imagine, upgrading smoothly along your regular tasks, no longer deep in legacy.

Subscribe and get my free email course with steps for upgrading your AngularJS app to the latest 1.6 safely and without a rewrite.

Get the modernization email course!

Comments