< Previous chapterNext chapter >
Last updated .
The previous chapters already showed some examples of how controllers and directives can communicate. This chapter is about a more generic way of communicating between objects with scope. .Net developers are comfortable with using events. The event concept is baked into the .Net framework and languages. A somewhat similar event concept is a basic component of programming the DOM, where events "bubble" up (and down, actually) the DOM structure. Angular offers a simple event framework, letting you post and handle events. Scope objects form a hierarchy, if you remember, which follows the hierarchy of the controllers, modules and directives that contain them. In Angular, one scope object can send a message to another scope object, as long the two are on the same branch in the hierarchy. For example, a scope object can post an event to an ancestor scope object.
In order to receive an event, you call the $scope.$on method, passing in the name of the event and a handler function. To post an event, you can use either the $scope.$emit or the $scope.$broadcast event. The two methods behave in the same way; the crucial difference is that $scope.$emit posts an event that bubble up the scope hierarchy, whereas $scope.$broadcast posts an event that trickle down the hierarchy.
To show an example of using events, I constructed an example with the very basic frame of a webshop. The root controller hosts a child controller, which in turn uses a custom shop directive. The latter simply adds a button that the user can click on to add a random item to a shopping cart:
emit.html
<!doctype html>
<html>
<head>
<title>Emit</title>
<script src="Scripts/Angular/angular-1.5.0-rc.0/angular.js"></script>
</head>
<body ng-app="app" ng-Controller="appController as vm">
<a href="#">Browse catalog</a><br/>
Shopping cart: {{ vm.cartItemCount }} items,
total: {{ vm.cartTotal }} €<br/>
<div ng-controller="shopController">
<div>Here you can browse the shop... (TODO)</div>
<shop></shop>
</div>
<script src="emit.js"></script>
</body>
</html>
The accompanying script file contains the definition of the directive and two controllers:
emit.js
(
function ()
{
var app = angular.module("app", []);
function ShopDirective()
{
return {
scope: {},
template: "<button ng-click='vm.clickHandler()'>Add some book to cart</button>",
controller: function ($scope)
{
var vm = this;
vm.clickHandler = function ()
{
var price = new Date().getMilliseconds();
var eventArgs = {
items: [ { Name: "Angular book", price: price } ],
timestamp: new Date(),
total: price,
};
$scope.$emit("ItemsAdded", eventArgs);
};
},
controllerAs: "vm",
};
}
app.directive("shop", ShopDirective);
function AppController(scope)
{
var vm = this;
vm.cartItemCount = 0;
vm.cartTotal = 0;
scope.$on("ItemsAdded", function (event, eventArgs)
{
vm.cartItemCount += eventArgs.items.length;
vm.cartTotal += eventArgs.total;
});
}
app.controller("appController", ["$scope", AppController]);
function ShopController()
{
}
app.controller("shopController", [ShopController]);
}
)();
$scope.$on: $on(name, listener)
.
This method is called to set up an event handler.
function(event, eventArgs...)
$scope.$emit: $emit(name, eventArgs)
.
This method is called to raise an event, which travels up the scope hierarchy.
$scope.$broadcast: $broadcast(name, eventArgs)
.
This method is called to raise an event, which travels down the scope hierarchy.
< Previous chapterNext : Unit testing >
2016 by Niels Hede Pedersen