Table of contents

< Previous chapterNext chapter >

Last updated .

Communicating between components

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 webshop
The webshop with 5 items in cart

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]); } )();
In this example, an event is posted from the shopDirective. The $emit method is used for that, causing the event to bubble up the hierarchy of scopes to the root scope. The appController scope responds to the event, because it has registered a handler for the event using the $on method. Notice that an event is identified by a simple string and arguments of any complexity can be passed as the event argument.
The scope hierarchy
The scope hierarchy

New stuff

$scope.$on: $on(name, listener). This method is called to set up an event handler.

$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 Linked in