Dependency Injection with AngularJS

Design, control, and manage your dependencies with AngularJS dependency injection


Alex Knol


78 Pages

6952 Reads

89 Downloads

English

PDF Format

2.73 MB

Java Script

Download PDF format


  • Alex Knol   
  • 78 Pages   
  • 25 Feb 2015
  • Page - 1

    read more..

  • Page - 2

    Dependency Injection with AngularJS Design, control, and manage your dependencies with AngularJS dependency injection Alex Knol BIRMINGHAM - MUMBAI read more..

  • Page - 3

    Dependency Injection with AngularJS Copyright © 2013 Packt Publishing All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews. Every effort has been made in the read more..

  • Page - 4

    Credits Author Alex Knol Reviewers Iwan van Staveren Ruoyu Sun Acquisition Editor James Jones Commissioning Editor Neil Alexander Technical Editors Sharvari H. Baet Dennis John Copy Editors Alisha Aranha Roshni Banerjee Tanvi Gaitonde Gladson Monteiro Shambhavi Pai Adithi Shetty Project Coordinator Sherin Padayatty Proofreader Simran Bhogal Indexer Rekha Nair Production Coordinator Kyle Albuquerque Cover Work Kyle read more..

  • Page - 5

    About the Author Alex Knol is a lifelong tech geek with a passion for automation. After spending some years away from software development, around the beginning of this century, he took up PHP development based on his early experiences with C and Pascal. Surprisingly, he has never really used web tools, but applications instead, to make websites, such as the platform read more..

  • Page - 6

    About the Reviewers Iwan van Staveren is a software architect. He has over 14 years of experience in developing all kinds of web applications. He loves working with the Symfony2 and AngularJs frameworks. He is owner of the privately-owned E-one Software. Ruoyu Sun is a designer and developer living in Hong Kong. He is passionate about programming and has been contributing read more..

  • Page - 7

    www.PacktPub.com Support files, eBooks, discount offers, and more You might want to visit www.PacktPub.com for support files and downloads related to your book. Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.PacktPub. com and as a print book customer, you are entitled to a read more..

  • Page - 8

    Table of Contents Preface 1 Chapter 1: Learning to Fly 5 Let's get going 5 Adding a controller 8 What about routes? 9 Showing a list 11 Adding a filter 12 Chart directives 13 Using services 15 Summary 16 Chapter 2: Better Code 17 Wiring up the backend 17 Duplicating code 19 Angular service to the rescue 21 The theory behind Dependency Injection 24 Summary read more..

  • Page - 9

    Table of Contents [ ii ] Chapter 5: Large Applications 55 Organizing your application 55 Going a bit larger 57 Organizing using dynamic teams 58 Using modules 58 Organizing using directives 60 Nesting controllers 60 More powerful nesting 61 Application communication 62 Events 62 Let the model speak 62 Summary 63 Index 65 read more..

  • Page - 10

    Preface Dependency Injection is a term often used in the world of object-oriented software design. AngularJS depends on it at its core. This book teaches you why and how to use Dependency Injection with AngularJS. What this book covers Chapter 1, Learning to Fly, will take you through the basics of an Angular application. This chapter prepares a sample app that will be read more..

  • Page - 11

    Preface [ 2 ] What you need for this book To play along with the examples in this book, you just need a working installation of NodeJS and a text editor. To view the output, a web browser is required. Who this book is for If you are a developer or software engineer, this book is ideal for you. You should have a basic understanding of JavaScript and web read more..

  • Page - 12

    Preface [ 3 ] New terms and important words are shown in bold. Warnings or important notes appear in a box like this. Tips and tricks appear like this. Reader feedback Feedback from our readers is always welcome. Let us know what you think about this book—what you liked or may have disliked. Reader feedback is important for us to develop titles that you really read more..

  • Page - 13

    Preface [ 4 ] Errata Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you find a mistake in one of our books—maybe a mistake in the text or the code—we would be grateful if you would report this to us. By doing so, you can save other readers from frustration and help us improve subsequent versions of this read more..

  • Page - 14

    Learning to Fly When you code larger applications in JavaScript, you soon run into a need for some kind of organization for your code. There are a great number of frameworks out there that can help you; the sheer number is enough to just keep you coding as you have done for years. Although there is a learning curve involved like in any framework or tool read more..

  • Page - 15

    Learning to Fly [ 6 ] This will download just a minified JavaScript file that you have to include in your HTML file. To get started, your HTML could look like the following: <!doctype html> <html lang="en" ng-app="myApp"> <head> <meta charset="utf-8"> <title>My First html page with AngularJS</title> </head> <body> read more..

  • Page - 16

    Chapter 1 [ 7 ] Valid HTML If you like valid HTML, Angular offers ways to specify instructions so that your pages will be completely valid HTML. For instance, you can prefix all the ng-* notations with x- or data- . Now what exactly is happening here? Just below the doctype declaration, you see ng-app . This is a general bootstrapping directive for Angular. In this read more..

  • Page - 17

    Learning to Fly [ 8 ] As you saw earlier, the input field was bound to an empty variable temp to begin with. What if we wanted to start with a temperature of, say, 17 degrees? Technically, we could set the value of temp to 17 in the template, but because one of our goals here is to have better code organization, we'll place this nicely inside a JavaScript read more..

  • Page - 18

    Chapter 1 [ 9 ] use strict is optional but helps you, as a developer, to create ECMAScript 5-compatible JavaScript and provides more feedback in supported browsers. For more information, refer to the following link, which is a good read among others http://ejohn.org/blog/ ecmascript-5-strict-mode-json-and-more/ . What about routes? Next to seeing the actual temperature in the current read more..

  • Page - 19

    Learning to Fly [ 10 ] <script src="app/js/app.js"></script> </body> </html> // partials/current.html Current temperature: <input ng-model='temp' type='number'/> Celcius <p ng-show="temp>=17">Not too bad! {{ temp }} degrees, {{ temp - 10 }} would be a little cold</p> <p ng-show="temp<17">{{ temp }} degrees, is a little chilly, read more..

  • Page - 20

    Chapter 1 [ 11 ] First the module is initialized with the name from the template tempApp . The empty array after the module name can contain dependencies for the module. Then the module is configured using $routeProvider as a dependency, which is used to redirect a URI to a partial HTML template using a specific controller. The notation of the controllers has read more..

  • Page - 21

    Learning to Fly [ 12 ] Adding a filter Let's say our users are only interested in temperatures above 15 degrees. We could modify the data in the controller. If we need this same data elsewhere, we could create a copy of the data and modify that for display. Angular has a neat feature called filters. There are several filters included with Angular, but it is simple read more..

  • Page - 22

    Chapter 1 [ 13 ] The filter now takes an optional argument as the minimum value to display. When you run the code without changing the template, it works exactly like before. To reflect the new functionality of our filter, we now also have changed the filter's name to minimum . To take advantage of the new feature, we have to specify the minimum temperature read more..

  • Page - 23

    Learning to Fly [ 14 ] The real work is now delegated to our new directive, leaving the template clean and concise: tempApp. directive('tempChart', [function(version) { return { template: '<div id="container"></div>', link: function(scope, element, attrs) { var chart = new Morris.Line({ read more..

  • Page - 24

    Chapter 1 [ 15 ] The output is shown as follows: The result is a page where the user can now use the number input to control the data visualized in the chart. Using services One last element of Angular that deserves attention is the concept of services. One of the built-in services is the location service. The location service provides read and write accesses read more..

  • Page - 25

    Learning to Fly [ 16 ] Summary In this chapter you have seen how to get started with AngularJS. First, we looked at the setup of an Angular project. Then we created a simple page with some angular bindings. We added a controller and another page. The second page showed just a list at first, but got upgraded to a nice chart. We immediately encapsulated the chart in read more..

  • Page - 26

    Better Code When we created our HistoryController , we put the historyData object containing days and their corresponding temperatures inside it. For demonstration purposes, this is not the end of the world, but the controller is useless without it. So the controller depends on this object to function correctly. The best thing to do here is to take the hash object read more..

  • Page - 27

    Better Code [ 18 ] First the data is moved out of the controller into a file somewhere on the filesystem. Notice the difference in the notation of JSON compared to the previous JavaScript notation. JSON doesn't allow keys to be unquoted. Next, we have to somehow get our controller to use the Parse SDK to get data from the backend. There are a few design read more..

  • Page - 28

    Chapter 2 [ 19 ] First, the Parse library needs to know our credentials in order to access the service. This is done in the Parse.initialize call. After that is done a local Reading object is created by extending Parse.Object . This connects our local object to a remote entity named reading . Then, a query is created on the collection of the Reading entities read more..

  • Page - 29

    Better Code [ 20 ] }, error: function (gameScore, error) { // The save failed. // error is a Parse.Error with an error code and description. } }); } read more..

  • Page - 30

    Chapter 2 [ 21 ] Angular service to the rescue To circumvent all these problems, Angular has a concept of services that we mentioned at the end of Chapter 1, Learning to Fly. Talking to the Parse API or service can be viewed as a service to the application. The service is responsible for initializing Parse and instantiating the Reading object that is ready for read more..

  • Page - 31

    Better Code [ 22 ] Let's take our new serviceModule one step further and extend it with a second service on top of our generic Parse service that will use the Parse instance to expose methods for query and save . This allows us to take some more code out of our controllers. angular.module('serviceModule', [function ($provide) { $provide.factory('parse', [function read more..

  • Page - 32

    Chapter 2 [ 23 ] alert("Error: " + error.code + " " + error. message); } }); } }; return serviceInstance; read more..

  • Page - 33

    Better Code [ 24 ] First of all, the Parse-specific code has been centralized and is extracted from the controllers. We can very easily use the reading service in many more classes with minimal lines of code. Reducing lines of code is not a goal of Dependency Injection but a side effect. Another advantage of separating the responsibilities is that the separate parts are read more..

  • Page - 34

    Chapter 2 [ 25 ] Initial Stands for Concept I Interface segregation principle (ISP) This principle states that many client-specific interfaces are better than one general-purpose interface. D Dependency inversion principle (DIP) This principal states that one should depend upon abstractions. Do not depend upon concretions. Dependency injection is one method following this principle. read more..

  • Page - 35

    Better Code [ 26 ] • Dependency Inversion principle: This principle resembles the subject of this book quite closely and is, in fact, related to it, but not as closely as you might think. Dependency inversion is about having high- and low-level components in a software project that depends on abstractions. Abstractions can be thought of as standard interfaces. In read more..

  • Page - 36

    Chapter 2 [ 27 ] $scope.save = function () { reading.save($scope.temp); } }; In the preceding example, we exposed the Parse service through the "reading" service. In the controller, we reached through the reading service and called a method on the Parse service with reading.backend. VERSION . This is a bad idea, because when something changes read more..

  • Page - 37

    Better Code [ 28 ] Summary In this chapter we have looked at simplifying our application by removing duplicate code and abstracting that functionality away into a service and then injecting that into different parts of the application. Afterwards, we looked at the SOLID principles and how they play a role in Dependency Injection. The Law of Demeter was the closing piece of read more..

  • Page - 38

    The Magic It is time we explain some of the inner workings of Angular. Angular does some neat things for us. It saves us from having to write a bunch of boilerplate code. Dependency Injection is baked into AngularJS and heavily used throughout. Another feature is a built-in subset of a jQuery functionality called jQLite. It contains all the necessary functions to make read more..

  • Page - 39

    The Magic [ 30 ] After the browser loads the HTML and parses it into a DOM, the angular.js script file is loaded. This can be added before or at the bottom of the <body> tag, although adding it at the bottom is preferred. Angular waits for the browser to fire the DOMContentLoaded event. This is similar to the way jQuery is bootstrapped, as read more..

  • Page - 40

    Chapter 3 [ 31 ] • It is also possible to define a controller to control a specific part of the HTML page, as we have shown in the first tempCtrl code snippet • We have also shown you how to use Angular's built-in router to manage your application using client-side routing As you can see, Angular extends the capabilities of HTML by providing a clever way read more..

  • Page - 41

    The Magic [ 32 ] These are essentially the same definitions and don't cause pollution in the global scope. The second difference that you may have noticed is in the way the dependencies are injected in the function. At the time of writing this book, most, if not all of the examples on the AngularJs website use the simple injection method. The dependencies are read more..

  • Page - 42

    Chapter 3 [ 33 ] If you prefer the definition without the array notation, there is still some hope. Angular provides a way to inform the injector service of the dependencies you are trying to inject. varCurrentCtrl = function($scope, reading) { $scope.temp = 17; $scope.save = function() { reading.save($scope.temp); } }; CurrentCtrl.$inject = ['$scope', 'reading']; read more..

  • Page - 43

    The Magic [ 34 ] Summary In this chapter, we started by looking at how AngularJS is bootstrapped. Then, we looked at how the injector works and why minification might ruin your plans there. We also saw that there are ways to avoid these problems by specifying dependencies differently. read more..

  • Page - 44

    Testing During the course of this book we have spoken about testing a few times, but never actually got into it. Now is the time to get our (testing) hands dirty. The reason we reserved a section for testing is because it is the second most important part of the development process, after your awesome code, of course. Any modern software development process should read more..

  • Page - 45

    Testing [ 36 ] With the rise of open source software, the adoption of test driven development has taken flight. When you want to contribute to a project, most of the time you will be required to accompany your code with tests. Writing decent tests for your code involves testing the definition of the functionality. You basically write down your requirements in a read more..

  • Page - 46

    Chapter 4 [ 37 ] Test your code, not the framework This eagerness is also a danger, because testing is a means to an end, not a purpose! You should only test your code and not the tools you embedded. An example is a test that checks if a scope variable was correctly shown on the page using the curly braces {{ }} , shown as follows: // pseudo code for our read more..

  • Page - 47

    Testing [ 38 ] When the test is executed, it will read like human language: "Adding a function should add two arguments". The describe function is used to put a description on your group of tests, or assertions, as they are sometimes called. This string has no functionality. The it() function starts a new test, which is also named with a string. Be sure to read more..

  • Page - 48

    Chapter 4 [ 39 ] Before we look at the tests, let's examine the specRunner.html file to find out how Jasmine gets all the files together. The header of the file looks like the following: <title>Jasmine Spec Runner</title> <link rel="shortcut icon" type="image/png" href="lib/jasmine-1.3.1/ jasmine_favicon.png"> <link rel="stylesheet" read more..

  • Page - 49

    Testing [ 40 ] After loading the Jasmine styles and libraries, the source files are loaded first and then the tests under /spec ; although the order in which the files are loaded doesn't matter. By the way, the term "spec" comes from "behavior specification", which is what drives behavior-driven tests. The inline JavaScript in the following code snippet is the read more..

  • Page - 50

    Chapter 4 [ 41 ] } }); }); As this beforeEach block has not been included in a describe() block, it will be executed before any Jasmine test. The value passed to the custom matcher is this.actual . An explanation of how to add a custom failure message can be found at https://github.com/pivotal/jasmine/wiki/Matchers#writing-new- matchers . Now let's change this read more..

  • Page - 51

    Testing [ 42 ] We started by adding a section for Angular that includes the Angular.js file. The next inclusion is angular-mocks.js . This file contains all kinds of functions that help us, or even better, help our testing framework test our Angular code after we simply include all our application code. Our first actual test specification is a file that doesn't exist read more..

  • Page - 52

    Chapter 4 [ 43 ] Every time you refresh the browser, the tests are run again and the result is shown. Now for the test code there are two describe blocks: the outer one tests filters and the inner one specifies the minimum filter. In the outer loop of the beforeEach block, the module for our application is loaded: beforeEach( module('tempApp') ); This happens read more..

  • Page - 53

    Testing [ 44 ] This new test prepares an array with data from the history.json file that was used in the first chapter. It then runs the array through the filter and checks if the correct number of items are returned. A more thorough test would be to iterate over the resulting array and check if there really aren't any values below 15 . Feel free to play with read more..

  • Page - 54

    Chapter 4 [ 45 ] This simple start of a test will fail, as shown in the following screenshot: As seen before, we have loaded the module tempApp . After which we instantiated the controller, as stated in the documentation: beforeEach(inject(function ($rootScope, $controller) { scope = $rootScope.$new(); $controller('HistoryCtrl', { $scope: read more..

  • Page - 55

    Testing [ 46 ] This is where it went wrong! The controller not only depends on the $scope variable, but also on our reading service. Since the controller depends on it, we can feed the controller a special version of this reading service that will supply static data. The benefit is that the outcome can be predefined and we don't need an Internet connection to read more..

  • Page - 56

    Chapter 4 [ 47 ] In these simple examples, the power of dependency injection really shows it's strength. We would have had a hard time testing the controller without it. If you want to see how the unit tests for other parts of the application are constructed, have a look in the Git repository for this book <packpub git url> . The Karma test runner The Angular read more..

  • Page - 57

    Testing [ 48 ] exclude: [ ], // test results reporter to use // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' reporters: ['progress'], // web server port port: 9876, // enable / disable colors in the output (reporters and logs) colors: true, // level of read more..

  • Page - 58

    Chapter 4 [ 49 ] singleRun: false, preprocessors: { } }); }; The config will load the same files as the Jasmine SpecRunner.html file we created before. There are some additional configuration parameters for the Karma test runner that are explained in the comments of the preceding code snippet. Additional information on the configuration read more..

  • Page - 59

    Testing [ 50 ] When we fire up Karma by executing this script, the output should look like the following: As long as you keep this window open, Karma will keep watching your files and rerunning all the unit tests. Notice the time it took to run the tests? The entire test suite for the Angular framework itself takes less than a second to run. To keep Karma read more..

  • Page - 60

    Chapter 4 [ 51 ] The end-to-end tests require us to have a running application server because this type of testing will act like a "real user," clicking and interacting with your application in other ways. We need to have a way to navigate pages and simulate this user interaction. The tool for this job is Protractor—a brand new testing framework based on Selenium and read more..

  • Page - 61

    Testing [ 52 ] BASE_DIR=`dirname $0` echo "" echo "Starting Protractor Server (https://github.com/angular/ protractor)" echo "--------------------------------------------------------------- ----" protractor config/selenium-conf.js Since Protractor runs on top of Selenium, there are many different setups and options available that go too far for our book. This setup will read end-to-end read more..

  • Page - 62

    Chapter 4 [ 53 ] Now that we are all set up, we can start coding our first test. This will be done in a new file in the test/e2e folder: // /test/e2e/app.js 'use strict'; describe('tempApp', function() { var ptor; describe('current page', function() { ptor = protractor.getInstance(); beforeEach(function() { ptor.get('/index.html'); }); read more..

  • Page - 63

    Testing [ 54 ] Even the output looks like the Karma output! More importantly, the browser opened your application and "saw" in the page that string 17 was present. In the next test we will try to have our test runner change the input box to something else and then test the outcome. The second test is appended to the test file within the current describe page read more..

  • Page - 64

    Large Applications Writing a large, single-page application using traditional methods that are based on DOM manipulation has turned out to be difficult to manage and maintain. As we have seen in this book, Angular brings a new paradigm to the table for creating more maintainable applications by using dependency injection. Even when using Angular, it is still entirely possible to read more..

  • Page - 65

    Large Applications [ 56 ] app.js --> application controllers.js --> application controllers directives.js --> application directives filters.js --> custom angular filters services.js --> custom angular services lib/ --> angular and 3rd party javascript libraries angular/ read more..

  • Page - 66

    Chapter 5 [ 57 ] Thanks to Igor Minar for the annotated directory structure. This being a "seed" application, it's tailored for simple projects. This setup puts all the Angular application code in single files, which will work fine for small to medium sized projects. The repository comes with a complete test setup with end-to-end unit tests to get you started. read more..

  • Page - 67

    Large Applications [ 58 ] The changing filesystem You would have to manually change files that are included in the main HTML file to stay in sync with your filesystem changes. When your JavaScript application is served from within a framework such as Ruby on Rails, Symfony (PHP), or NodeJS using Brunch.io, organizing your app is simplified considerably. They, and others, read more..

  • Page - 68

    Chapter 5 [ 59 ] checkbox.js → checkbox directive services/ logging.js → central application logging service parse.js → parse data backend service config.js → central configuration service admin/ read more..

  • Page - 69

    Large Applications [ 60 ] Organizing using directives Directives have been mentioned a few times already in this chapter. So far, we have used them to encapsulate JavaScript code which is not Angular aware, such as the third-party charting library from the previous chapters. Another way to use directives is to abstract pieces of functionality, so that their complexity is read more..

  • Page - 70

    Chapter 5 [ 61 ] When testing nested controllers, it is very easy to stub scope variables of the parent controllers so that they are available inside the sub controller. When you used a setter to set a parent scope variable, it should also be stubbed in the test: describe('nested controller', function() { var $scope, ctrl; it('should have a value', read more..

  • Page - 71

    Large Applications [ 62 ] We won't even try to replace their excellent documentation, but it centers around state instead of URL and makes it possible to access pages in a certain state using a URL. So, the state of a page becomes a part of the routing possibilities, and as such, will allow you to step over the limitation of the default routing system. So, hop read more..

  • Page - 72

    Chapter 5 [ 63 ] In Angular, it makes sense to capture the dragging events and update the position in the model so the renderer can update its position on the screen. When the element is moving over the screen, we might need to show the actual coordinates of the object, the left and top CSS properties, in the sidebar. This can then easily be done by binding read more..

  • Page - 73

    read more..

  • Page - 74

    Index Symbols $inject property 33 $provide function 46 $scope.save function 20 $scope.temp variable 20 <BODY> tag 10 A add() function 38 Angular about 29 program flow 29, 30 Angular e2e testing 54 Angular JS downloading 5, 6, 7 Angular projects testing 37 angular service 21, 23, 24 annotation 31 application communication events 62 model-driven approach 62, read more..

  • Page - 75

    [ 66 ] G green 36 H hashbangs (#!) 10 HistoryController 17 historyData property 11 I injecting ways 31-33 Interface segregation principle (ISP) 25 it() function 38, 53 J Jasmine 37 JavaScript library getting started 5 jQuery tool 6 K Karma test runner 47, 49, 50 KnockoutJS 6 L larger application organizing 57, 58 Law of Demeter 26, 27 Liskov substitution read more..

  • Page - 76

    Thank you for buying Dependency Injection with AngularJS About Packt Publishing Packt, pronounced 'packed', published its first book "Mastering phpMyAdmin for Effective MySQL Management" in April 2004 and subsequently continued to specialize in publishing highly focused books on specific technologies and solutions. Our books and publications share the experiences of your fellow IT read more..

  • Page - 77

    Angular JS Directives ISBN: 978-1-78328-033-9 Paperback: 110 pages Learn how to craft dynamics directives to fuel your single-page web applications using AngularJS 1. Learn how to build an AngularJS directive 2. Create extendable modules for plug-and-play usability 3. Build apps that react in real-time to changes in your data model Mastering Web read more..

  • Page - 78

    Ext JS 4 Plugin and Extension Development ISBN: 978-1-78216-372-5 Paperback: 116 pages A hands-on development of several Ext JS plugins and extensions 1. Easy-to-follow examples on ExtJS plugins and extensions 2. Step-by-step instructions on developing ExtJS plugins and extensions 3. Provides a walkthrough of several useful ExtJS libraries and communities read more..

Write Your Review