In the previous part, I talked fairly detailed about how the scopes use prototypical inheritance, and how we can use this to our advantage by either using simple property types, or by using complex types.
In this part, I want to cover some functionality given to us by Angular when using the scope…
When Angular defines the root scope for us, it gives us some functionality. The root scope object includes a bunch of members that we can use to perform different things. Some of them way more complex than I want to cover now, and some that I think needs to be covered now.
The parts I don’t want to cover now are mostly used when building directives, or doing funky stuff that needs to be handled a bit special. For normal everyday use, you can survive without them in most cases… Some of it will be covered in a later part when I try to explain how the databinding in Angular works internally. But for now, let’s just pretend it is all magic, and that we should leave the magic knobs and buttons alone…
The parts I want to cover are $broadcast(), $emit() and $on(), as well as $watch() and $watchCollection().
As you can see, the things I have said that I want to cover are all methods starting with “$”, which you should know by now, means that they are functionality offered by Angular… In this case given to use by the prototypical inheritance involved in the scope object.
Let’s start with looking at $watch(). The $watch() and $watchCollection() are methods added to the scope object to support getting notified when the scope changes. The $watch() method is for listening to changes in the scoped properties, while $watchCollection() is for listening to changes in collections. I will come back to the $watchCollection() later, but let’s start with $watch().
The $watch() function takes 1 to 3 parameters. The most common scenario includes 2. The 2 can either be a string and a function, or two functions. In this case, I will start with the slightly less common one, which is the one with 2 functions. But before we look at that, I just want to include a VERY short explanation of how databinding works in Angular…
Whenever something changes the scope, the scope needs to be told that something has been changed. In most cases, this is done by the directive that causes the change, for example the ngModel directive. The ngModel directive will listen to changes to an input control, and whenever it changes, it updates the scope, and tells it that it has changed. Whenever the scope is told that it has been changed, it starts a loop that will go through any registered watcher, and ask it if it is interested in the change. It does this by asking it to evaluate the a value on the scope that it is interested in. If the value is different than it was the previous time it was asked, the watchers listener method is called. After all the watcher have been run, another pass is done to see if any of the watchers changed the scope in a way that any of the other watchers were interested in. It keeps looping like this as long as any of the watchers want to run (up until a certain number of runs). This is called the digest loop.
When you add a watcher, the first function passed in is is responsible evaluating the value that the digest loop uses to figure out if the watcher is interested or not. To do this, it gets the scope object passed in.
The second function is the function that is run whenever the watcher is watching a value that has changed. That is whenever the first function returns a value that is different than the previous run.
The second function gets 3 parameters passed in. The new value, the old value and the scope. Using these parameters, it can then do whatever it wants.
Let’s demo this by creating a very simple test page like this
<!DOCTYPE html>
<html data-ng-app="myModule">
<head>
<title>A simple introduction to AngularJS - Part 5</title>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/app.js"></script>
</head>
<body data-ng-controller="myController">
<button data-ng-click="change()">Change</button>
</body>
</html>
As you can see, it is just a simple angular application page, with a single controller, and a single button connected to a function on the scope called change(). The JavaScript for this looks like this
angular.module('myModule',[])
.controller('myController',['$scope', function($scope) {
$scope.prop = 'Hello World';
$scope.change = function() {
$scope.prop = 'Hello Mama';
};
}]);
As you can see, all we have in the controller is some code for adding a property called prop to the scope, and a scope property of type function, called change(). The change() function changes the value of the prop property of the scope.
Now, let’s add a listener that logs any changes to the prop property
angular.module('myModule',[])
.controller('myController',['$scope', function($scope) {
...
$scope.$watch(function(scope) {
console.log('Evaluation function called. Returning: ' + scope.prop);
return scope.prop;
}, function(newValue, oldValue, scope) {
console.log('Property changed from ' + oldValue + ' to ' + newValue);
});
}]);
If we not run this in a browser, with the developer tools open we will see
Evaluation function called. Returning: Hello World app.js:9
Property changed from Hello World to Hello World app.js:12
Evaluation function called. Returning: Hello World app.js:9
The first log entry tells us that the evaluation function has been called. This is when everything is loaded up. The second tells us that the property changed from “Hello World” to “Hello World”. Que!? Well, this is actually to be expected. This is when the watcher is initialized. The evaluation function will run at initialization, and since it is the first time, the returned value will always be different than previous…
The third entry is that the evaluation function is run, and that it returns “Hello World”. This time however, the value hasn’t changed, so the listener isn’t called.
Side note: DO NOT log to the console like this. It makes your controllers un-testable, and will fail in IE as IE does not have a console variable available until you open the developer tools… Instead you should get an instance of $log injected, and use that to do your logging. But in this case I just want to make it simple…
If we press the button and change the value, the log changes and adds the following line
Evaluation function called. Returning: Hello Mama app.js:9
Property changed from Hello World to Hello Mama app.js:12
Evaluation function called. Returning: Hello Mama app.js:9
First, the evaluation function is called, returning “Hello Mama”, which is different than the previous value of “Hello World”. Next, the listener method is called. And finally the evaluation method is called again, returning “Hello Mama” again, which is the same as the previous run, so the listener isn’t called.
If I press the button again, I only get a single log entry
Evaluation function called. Returning: Hello Mama app.js:9
as once again, the value returned is the same as before…
That is all there is to using the $watch() function. However, I did mention that the function could be called with 1 to 3 methods… Passing only a single function will give you a function that is called every single time that the digest loop runs. This function needs to be idempotent as it might run several times during the same digest…
The next version is to pass a string and a function. The string will be an expression that will be evaluated against the scope object to figure out if the value has changed or not. It is by far the most common way to use the $watch() function. Instead of having a function that returns the value to compare against, we just pass in the “path” on the scope to look at. In this case, the registration would look like this
$scope.$watch('prop', function(newValue, oldValue, scope) {
console.log('Property changed from ' + oldValue + ' to ' + newValue);
});
The expression used can be more complicated than just a property name. It can go several objects deep and so on. And internally, it will be wrapped in a function that evaluates it just like we did manually…
The third, and last property, is called objectEquality. It is a boolean defining how the object returned from the evaluation function should be compared for equality. By default, the compare is done by reference, which means that we wont notice changes to properties on complex properties. Passing in true will tell Angular that you want the values to compared by comparing the object instead of just the reference. Basically a deep compare vs a reference compare. This is not the default as it is a much heavier task than just comparing reference. Only use this if you really have to…
The $watchCollection() function is very similar to the $watch() function. However, it doesn’t perform a reference equality comparison. Instead, it uses a shallow compare, which means that it will look at the current object and compare it based on its value(s). If the evaluation function returns an array, it does the comparison based on the items in the array. If items are added, removed or changed, it will consider it being changed. However, changes in the actual instances won’t be checked. Ii f the watched object is an object, it will instead check if any of its properties has changed…
Side note: One thing to note here is the way that comparing instances in an array is actually a lot more similar to comparing instance properties than one might think. In JavaScript, objects are just property bags. This means that all objects have an indexer that can return a properties value based on any property name. For example obj.prop is exactly the same as obj[“prop”]. This means that we can access property very flexibly, and even use property names that are not allowed to be accessed using dot notation. An array works in exactly the same way, except for the fact that the indexer uses a number, such as arr[2]. This is actually possible to do in an object as well…however, an array also contains a property name length which returns the highest index number that has been used. So by assigning the 999th entry using arr[999] = “foo” doesn’t actually generate a list of 999 empty entries and one populated. It just generates an object with a value with the indexer 999. But, the length property will return 1000.
Next up is $broadcast(), $emit() and $on(). These are functions added to the scope object to give us a way to communicate up and down the scope inheritance chain using messages… The easiest way to explain this is by adding a demo.
Index.htm
<!DOCTYPE html>
<html data-ng-app="myMessagingModule">
<head>
<title>A simple introduction to AngularJS - Part 5</title>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/app.js"></script>
</head>
<body data-ng-controller="myMessagingParentController">
<div data-ng-controller="myMessagingChildController">
</div>
<div data-ng-controller="myMessagingChildController">
<div data-ng-controller="myMessagingGrandChildController">
</div>
</div>
</body>
</html>
Which with some styling looks like this

As you can see, the white area (the body) is using the myMessagingParentController, the pink is using the myMessagingChildController and the yellow is using the myMessagingGrandChildController.
The JavaScript looks like this
angular.module('myMessagingModule',[])
.controller('myMessagingParentController',['$scope', function($scope) {
}])
.controller('myMessagingChildController',['$scope', function($scope) {
}])
.controller('myMessagingGrandChildController',['$scope', function($scope) {
}]);
So far, nothing too exciting… Let’s try adding some messaging to the mix using $broadcast() and $emit().
I’m going to add a broadcast() and an emit() function to each scope like this
angular.module('myMessagingModule',[])
.controller('myMessagingParentController',['$scope', function($scope) {
$scope.emit = function() {
$scope.$emit("EmitMessage", { message: 'Message emitted from the parent controlled' });
};
$scope.broadcast = function() {
$scope.$broadcast("BroadcastMessage", { message: 'Message broadcasted from the parent controller' });
};
}])
.controller('myMessagingChildController',['$scope', function($scope) {
$scope.emit = function() {
$scope.$emit("EmitMessage", { message: 'Message emitted from the child controlled' });
};
$scope.broadcast = function() {
$scope.$broadcast("BroadcastMessage", { message: 'Message broadcasted from the child controller' });
};
}])
.controller('myMessagingGrandChildController',['$scope', function($scope) {
$scope.emit = function() {
$scope.$emit("EmitMessage", { message: 'Message emitted from the child controlled' });
};
$scope.broadcast = function() {
$scope.$broadcast("BroadcastMessage", { message: 'Message broadcasted from the child controller' });
};
}]);
Ok, so what am I doing here? Well, all scopes now have 2 functions, the emit() and broadcast() functions. They do pretty much the same, except the send out different messages. They way that they transmit the messages, is by calling the $emit() and $broadcast() methods of the scope object.
The two methods have the same signature. They take a message name, and a message, or “args” as the Angular documentation calls it. However, they do 2 different things. The $broadcast() function will send a message down the inheritance hierarchy, sending it to every single scope that inherits from the current scope, while the $emit() function will do the opposite and send it up the inheritance hierarchy, notifying every single parent up the chain.
Ok, now that we have the messages going up and down the inheritance chain, what do we do? Well, we have to start listening for the messages using the $on() function. The $on() method takes a couple of parameters, the first being the name of the event to listen to, and the second being a function taking 2 parameters, an event parameter and the args being sent by the sender.
So, let’s modify the controllers to listen to the messages
angular.module('myMessagingModule',[])
.controller('myMessagingParentController',['$scope', function($scope) {
...
$scope.$on('BroadcastMessage', function(e,args) {
console.log("Broadcast message received in parent controller: " + args.message);
});
$scope.$on('EmitMessage', function(e,args) {
console.log("Emit message received in parent controller: " + args.message);
});
}])
.controller('myMessagingChildController',['$scope', function($scope) {
...
$scope.$on('BroadcastMessage', function(e,args) {
console.log("Broadcast message received in child controller: " + args.message);
});
$scope.$on('EmitMessage', function(e,args) {
console.log("Emit message received in child controller: " + args.message);
});
}])
.controller('myMessagingGrandChildController',['$scope', function($scope) {
...
$scope.$on('BroadcastMessage', function(e,args) {
console.log("Broadcast message received in grand child controller: " + args.message);
});
$scope.$on('EmitMessage', function(e,args) {
console.log("Emit message received in grand child controller: " + args.message);
});
}]);
As you can see, all we do is log a message to the console when a broadcast or emit message is received.
As you can also see, the args parameter is just the instance being passed in as the second parameter to the $emit() and $broadcast() functions… The first parameter, the e, on the other hand, is a specific object containing information about the event. Information and functionality such as the original scope (targetScope), the current scope (currentScope), a method called stopPropagation() that will stop the message from bubbling up further in the case of an emit and so on.
The last thing to do is to make sure that we can call these methods. In this case, let’s add a few buttons to the HTML. Like this
<!DOCTYPE html>
<html data-ng-app="myMessagingModule">
<head>
...
</head>
<body data-ng-controller="myMessagingParentController">
<button data-ng-click="broadcast()">Broadcast</button>
<button data-ng-click="emit()">Emit</button>
<div data-ng-controller="myMessagingChildController">
<button data-ng-click="broadcast()">Broadcast</button>
<button data-ng-click="emit()">Emit</button>
</div>
<div data-ng-controller="myMessagingChildController">
<button data-ng-click="broadcast()">Broadcast</button>
<button data-ng-click="emit()">Emit</button>
<div data-ng-controller="myMessagingGrandChildController">
<button data-ng-click="broadcast()">Broadcast</button>
<button data-ng-click="emit()">Emit</button>
</div>
</div>
</body>
</html>
Now that we have a UI that we can use to emit and broadcast messages in the scope hierarchy, let’s examine what happens when we click them.
Clicking the Broadcast button connected to the parent controller will generate a console output that looks like this
Broadcast message received in parent controller: Message broadcasted from the parent controller app.js:11
Broadcast message received in child controller: Message broadcasted from the parent controller app.js:26
Broadcast message received in child controller: Message broadcasted from the parent controller app.js:26
Broadcast message received in grand child controller: Message broadcasted from the parent controller app.js:41
As you can see, the message was picked up in the parent controller to begin with. This tells us that broadcasting messages starts at the current scope level.
Next, both the child controllers get the message. And finally the grand child controller gets it.
Conclusion? Using $broadcast() will send messages down the scope hierarchy including the scope that it was broadcasted on.
Let’s try pushing the Emit button of the parent controller… Result…
Emit message received in parent controller: Message emitted from the parent controlled app.js:14
Emit goes up the hierarchy, starting with the current scope. So in this case, as there is no parent scope listening “above” the parent controller, the only thing logged will be from the parent controller itself. However, if we instead push the Emit button connected to the grand child controller, the console looks like this
Emit message received in grand child controller: Message emitted from the child controlled app.js:44
Emit message received in child controller: Message emitted from the child controlled app.js:29
Emit message received in parent controller: Message emitted from the child controlled app.js:14
which is kind of what was to be expected. The grand child controller picks up the message to begin with. Then the child controller. And finally the parent controller. However, if we wanted to stop the bubbling at any level, we could just call stopPropagation() on the event parameter.
Ok, that’s all we need to know about $emit() and $broadcast(). One thing to note is that since we always can access the application root scope using $rootScope, we can always push messages down through every single controller if we want to. However, we should avoid this as much as possible. If we need messaging that goes across controllers like this, it is much better to use a pub/sub service like Postal.js or similar, and wrap that in a service (building custom services will be covered in a later post…).
I think that was all for this time… Next post will focus on how we build custom services in Angular.
Cheers!