AngularJS Web Application Development Cookbook

More Information
Learn
  • Architect AngularJS applications that are designed to scale
  • Implement best practices used by the top AngularJS developers
  • Write robust test suites with full application coverage
  • Create application modules with maximum reusability and extensibility
  • Master the most difficult aspects of AngularJS such as animation, testing, and promises
  • Learn how to integrate all the new components introduced in the latest 1.3 release
  • Discover syntax and browser tricks to make using AngularJS even better
  • Optimize your AngularJS application for maximum performance
About

Packed with easy-to-follow recipes, this practical guide will show you how to unleash the full might of the AngularJS framework. Skip straight to practical solutions and quick, functional answers to your problems without hand-holding or slogging through the basics. Avoid antipatterns and pitfalls, and squeeze the maximum amount out of the most powerful parts of the framework, from creating promise-driven applications to building an extensible event bus. Throughout, take advantage of a clear problem-solving approach that offers code samples and explanations of components you should be using in your production applications.

 

 

Read an Extract from the book

Configuring and using AngularJS events

AngularJS offers a powerful event infrastructure that affords you the ability to control the application in scenarios where data binding might not be suitable or pragmatic. Even with a rigorously organized application topology, there are lots of applications for events in AngularJS.

How to do it…

AngularJS events are identified by strings and carry with them a payload that can take the form of an object, a function, or a primitive. The event can either be delivered via a parent scope that invokes $scope.$broadcast(), or a child scope (or the same scope) that invokes $scope.$emit().

The $scope.$on() method can be used anywhere a scope object can be used, as shown here:

(app.js) angular.module('myApp', []) .controller('Ctrl', function($scope, $log) { $scope.$on('myEvent', function(event, data) { $log.log(event.name + ' observed with payload ', data); }); });

Broadcasting an event

The $scope.$broadcast() method triggers the event in itself and all child scopes. The 1.2.7 release of AngularJS introduced an optimization for $scope.$broadcast(), but since this action will still bubble down through the scope hierarchy to reach the listening child scopes, it is possible to introduce performance problems if this is overused. Broadcasting can be implemented as follows:

(app.js) angular.module('myApp', []) .directive('myListener', function($log) { return { restrict: 'E', // each directive should be given its own scope scope: true, link: function(scope, el, attrs) { // method to generate event scope.sendDown = function() { scope.$broadcast('myEvent', {origin: attrs.local}); }; // method to listen for event scope.$on('myEvent', function(event, data) { $log.log( event.name + ' observed in ' + attrs.local + ', originated from ' + data.origin ); }); } }; }); (index.html) <div ng-app="myApp"> <my-listener local="outer"> <button ng-click="sendDown()">Send Down</button> <my-listener local="middle"> <my-listener local="first inner"></my-listener> <my-listener local="second inner"></my-listener> </my-listener> </my-listener> </div>

In this setup, clicking on the Send Down button will log the following in the browser console:

myEvent observed in outer, originated from outer myEvent observed in middle, originated from outer myEvent observed in first inner, originated from outer myEvent observed in second inner, originated from outer

Emitting an event

As you might expect, $scope.$emit() does the opposite of $scope.$broadcast(). It will trigger all listeners of the event that exist within that same scope, or any of the parent scopes along the prototype chain, all the way up to $rootScope. This can be implemented as follows:

(app.js) angular.module('myApp', []) .directive('myListener', function($log) { return { restrict: 'E', // each directive should be given its own scope scope: true, link: function(scope, el, attrs) { // method to generate event scope.sendUp = function() { scope.$emit('myEvent', {origin: attrs.local}); }; // method to listen for event scope.$on('myEvent', function(event, data) { $log.log( event.name + ' observed in ' + attrs.local + ', originated from ' + data.origin ); }); } }; }); (index.html) <div ng-app="myApp"> <my-listener local="outer"> <my-listener local="middle"> <my-listener local="first inner"> <button ng-click="sendUp()"> Send First Up </button> </my-listener> <my-listener local="second inner"> <button ng-click="sendUp()"> Send Second Up </button> </my-listener> </my-listener> </my-listener> </div>

In this example, clicking on the Send First Up button will log the following to the browser console:

myEvent observed in first inner, originated from first inner myEvent observed in middle, originated from first inner myEvent observed in outer, originated from first inner

Clicking on the Send Second Up button will log the following to the browser console:

myEvent observed in second inner, originated from second inner myEvent observed in middle, originated from second inner myEvent observed in outer, originated from second inner

Deregistering an event listener

Similar to $scope.$watch(), once an event listener is created, it will last the lifetime of the scope object they are added in. The $scope.$on() method returns the deregistration function, which must be captured upon declaration. Invoking this deregistration function will prevent the scope from evaluating the callback function for this event. This can be toggled with a setup/teardown pattern, as follows:

(app.js) angular.module('myApp', []) .controller('Ctrl', function($scope, $log) { $scope.setup = function() { $scope.teardown = $scope.$on('myEvent',function(event, data) { $log.log(event.name + ' observed with payload ', data); }); }; });

Invoking $scope.setup() will initialize the event binding, and invoking $scope.teardown() will destroy that binding.

 
Features
  • Understand how to design and organize your AngularJS application to make it efficient, performant, and scaleable
  • Discover patterns and strategies that will give your insights into the best ways to construct production AngularJS applications
  • Get the most out of AngularJS by gaining exposure to real-world examples
Page Count 346
Course Length 10 hours 22 minutes
ISBN 9781783283354
Date Of Publication 26 Dec 2014

Authors

Matt Frisbie

Matt Frisbie is currently a software engineer at Google. He was the author of the Packt Publishing bestseller AngularJS Web Application Development Cookbook and also has published several video series through O'Reilly. He is active in the Angular community, giving presentations at meetups and doing webcasts.