AngularJS Essentials

Design and construct reusable, maintainable, and modular web applications with AngularJS


Rodrigo Branas


180 Pages

19543 Reads

97 Downloads

English

PDF Format

1.07 MB

Java Script

Download PDF format


  • Rodrigo Branas   
  • 180 Pages   
  • 25 Feb 2015
  • Page - 1

    read more..

  • Page - 2

    AngularJS Essentials Design and construct reusable, maintainable, and modular web applications with AngularJS Rodrigo Branas BIRMINGHAM - MUMBAI read more..

  • Page - 3

    AngularJS Essentials Copyright © 2014 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 preparation of this read more..

  • Page - 4

    Credits Author Rodrigo Branas Reviewers Andrei M. Eichler Cleberson C. C. Faccin Ruoyu Sun Felipe Trevisol Commissioning Editor Pramila Balan Acquisition Editor Harsha Bharwani Content Development Editor Sharvari Tawde Technical Editors Shiny Poojary Kirti Pujari Akash Rajiv Sharma Copy Editors Roshni Banerjee Mradula Hegde Alfida Paiva Project Coordinator Aboli Ambardekar Proofreaders Simran Bhogal Maria Gould read more..

  • Page - 5

    About the Author Rodrigo Branas is a software architect, author, and international speaker on software development based in Brazil, with more than 12 years of experience in developing enterprise applications. Lately, he has been participating in the development of many successful products based on the AngularJS framework. A major part of these applications were made available to the read more..

  • Page - 6

    Acknowledgments Writing this book was an incredible challenge! Throughout this time, I had the pleasure to count on my lovely wife, Rosana Branas, who provided me with all the inspiration, motivation, and affection that I needed. Also, I am very happy and glad about sharing this experience with my reviewers: Felipe Trevisol, Cleberson Faccin, Andrei Eichler, and Ruoyu Sun. They read more..

  • Page - 7

    About the Reviewers Andrei M. Eichler is a young developer with a great passion for learning. His main experiences include working with large Postgres databases and Java, and he is now venturing into Scala, performant JavaScript, and web application development. Cleberson C. C. Faccin is a graduate in Systems Information from Universidade Federal de Santa Catarina, Brazil. Since read more..

  • Page - 8

    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 - 9

    read more..

  • Page - 10

    Table of Contents Preface 1 Chapter 1: Getting Started with AngularJS 7 Introduction to AngularJS 8 Architectural concepts 9 Setting up the framework 10 Organizing the code 12 Four ways to organize the code 13 The inline style 13 The stereotyped style 13 The specific style 14 The domain style 15 Summary 15 Chapter 2: Creating Reusable Components with Directives 17 read more..

  • Page - 11

    Table of Contents [ ii ] The ngIf directive 31 The ngInclude directive 31 Refactoring application organization 32 Creating our own directives 34 template 35 templateUrl 36 replace 36 restrict 37 scope 38 transclude 42 link 43 require 44 controller 46 compile 47 Animation 48 How it works? 48 Animating ngRepeat 49 Animating ngHide 50 Animating ngClass 50 Summary read more..

  • Page - 12

    Table of Contents [ iii ] Chapter 4: Dependency Injection and Services 67 Dependency injection 68 Creating services 69 Creating services with the factory 70 Creating services with the service 74 Creating services with the provider 75 Using AngularJS built-in services 76 Communicating with the backend 76 HTTP, REST, and JSON 76 Creating an HTTP facade 82 Headers 84 read more..

  • Page - 13

    Table of Contents [ iv ] Chapter 7: Unit Testing 121 The Jasmine testing framework 122 Testing AngularJS components 124 Services 125 Controllers 126 Filters 128 Directives 129 Creating the element with the directive 130 Compiling the directive 130 Calling the link function with the scope 130 Invoking the digest cycle 130 Mocking with $httpBackend 132 Running tests with read more..

  • Page - 14

    Preface For more than 12 years, I have been developing all kinds of web applications, and along the way, I have had the opportunity to experience the vast majority of frameworks on the Java platform. In 2008, I moved from an architecture highly based on backend web frameworks such as Struts and JSF to experience new challenges at the frontend. I think the main goal read more..

  • Page - 15

    Preface [ 2 ] Only 2 months later, I launched my first web application based entirely on AngularJS, and honestly, I cannot imagine writing this same application using another kind of technology in this short period of time. I was so excited about it that I wrote an article on using AngularJS with Spring MVC and Hibernate for a magazine called Java Magazine. After that, read more..

  • Page - 16

    Preface [ 3 ] Chapter 4, Dependency Injection and Services, explains how we are going to create reusable and decoupled components by implementing services and using the dependency injection mechanism. Chapter 5, Scope, discusses how scope is one of the main concepts of the framework. In this chapter, we will discover the best practices to deal with scope. Chapter 6, Modules, read more..

  • Page - 17

    Preface [ 4 ] A block of code is set as follows: $http.get("/cars") .success(function(data, status, headers, config) { $scope.car = data; }) .error(function(data, status, headers, config) { console.log(data); }); When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold: read more..

  • Page - 18

    Preface [ 5 ] 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 get the most out of. To send us general feedback, simply send an e-mail to feedback@packtpub.com , and mention the book title via the subject of read more..

  • Page - 19

    Preface [ 6 ] Piracy Piracy of copyright material on the Internet is an ongoing problem across all media. At Packt, we take the protection of our copyright and licenses very seriously. If you come across any illegal copies of our works, in any form, on the Internet, please provide us with the location address or website name immediately so that we can pursue a remedy. read more..

  • Page - 20

    Getting Started with AngularJS HyperText Markup Language (HTML) was created in 1990 by Tim Berners-Lee—a famous physics and computer scientist—while he was working at CERN, the European Organization for Nuclear Research. He was motivated about discovering a better solution to share information among the researchers of the institution. To support that, he also created the read more..

  • Page - 21

    Getting Started with AngularJS [ 8 ] This chapter will introduce you to the most important concepts of AngularJS. The topics that we'll be covering in this chapter are: • Introduction to AngularJS • Understanding the architectural concepts • Setting up the framework • Organizing the code Introduction to AngularJS Created by Miško Hevery and Adam Abrons in 2009, AngularJS is an open read more..

  • Page - 22

    Chapter 1 [ 9 ] Architectural concepts It's been a long time since the famous Model-View-Controller (MVC) pattern started to gain popularity in the software development industry and became one of the legends of the enterprise architecture design. Basically, the model represents the knowledge that the view is responsible for presenting, while the controller mediates the read more..

  • Page - 23

    Getting Started with AngularJS [ 10 ] The following diagram exhibits the interaction between the AngularJS architecture components: Source: Official documentation (www.angularjs.org) Setting up the framework The configuration process is very simple and in order to set up the framework, we start by importing the angular.js script to our HTML file. After that, we need to create the read more..

  • Page - 24

    Chapter 1 [ 11 ] Downloading the example code You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com . If you purchased this book elsewhere, you can visit http://www.packtpub. com/ support and register to have the files e-mailed directly to you. index.html – Parking Lot Application <!doctype html> <!-- read more..

  • Page - 25

    Getting Started with AngularJS [ 12 ] </thead> <tbody> <!-- Iterating over the cars --> <tr ng-repeat="car in cars"> <!-- Showing the car's plate --> <td>{{car.plate}}</td> </tr> </tbody> </table> read more..

  • Page - 26

    Chapter 1 [ 13 ] This is a tough decision and there are many different ways to decide on these factors, but in most cases, it will depend simply on the purpose and the size of the application. For the time being, our challenge is to define an initial strategy that allows the team to evolve and enhance the architecture alongside application development. The answers read more..

  • Page - 27

    Getting Started with AngularJS [ 14 ] app.js -> main application script controllers.js -> all controllers script directives.js -> all directives script filters.js -> all filters script services.js -> all services script lib/ read more..

  • Page - 28

    Chapter 1 [ 15 ] In this approach, if the number of files in each directory becomes oversized, it is better to start thinking about adopting another strategy, such as the domain style. The domain style With a complex domain model and hundreds of components, an enterprise application can easily become a mess if certain concerns are overlooked. One of the best ways to read more..

  • Page - 29

    read more..

  • Page - 30

    Creating Reusable Components with Directives The Document Object Model (DOM) is a convention created by W3C in 1998 for documents written in HTML, XHTML, and XML in an object tree, which is used by the browsers throughout the rendering process. By means of the DOM API, it is possible to traverse the hierarchical structure of the tree to access and manipulate read more..

  • Page - 31

    Creating Reusable Components with Directives [ 18 ] The following diagram describes the bootstrapping process of the framework that is performed during the compilation process: Browser AngularJS Dynamic DOM (view) Static DOM $injector $rootScope ng-app="module" DOM Content Loaded Event HTML $compile $compile (dom) ($rootScope) Source: Official documentation (www.angularjs.org) This chapter will present read more..

  • Page - 32

    Chapter 2 [ 19 ] The directive can be applied as an attribute, element, class, and even as a comment, using the camelCase syntax. However, because HTML is case insensitive, we can use a lowercase form. For the ngModel directive, we can use ng-model , ng:model , ng_model , data-ng-model , and x-ng-model in the HTML markup. Using AngularJS built-in directives By default, read more..

  • Page - 33

    Creating Reusable Components with Directives [ 20 ] <script> var parking = angular.module("parking", []); </script> </head> <body> </body> </html> There can be only one ngApp directive in the same HTML document that will be loaded and bootstrapped by the framework automatically. However, it's possible to read more..

  • Page - 34

    Chapter 2 [ 21 ] Nested controllers Sometimes, our controller can become too complex, and it might be interesting to split the behavior into separated controllers. This can be achieved by creating nested controllers, which means registering controllers that will work only inside a specific element of the view, as shown in the following code: <body read more..

  • Page - 35

    Creating Reusable Components with Directives [ 22 ] The ngBindHtml directive Sometimes, it might be necessary to bind a string of raw HTML. In this case, the ngBindHtml directive can be used in the same way as ngBind ; however, the only difference will be that it does not escape the content, which allows the browser to interpret it as shown in the following code: read more..

  • Page - 36

    Chapter 2 [ 23 ] In the following code, we will iterate over the cars array and assign each element to the car variable: index.html <!doctype html> <html ng-app="parking"> <head> <title>[Packt] Parking</title> <script src="angular.js"></script> <script> var parking = angular.module("parking", read more..

  • Page - 37

    Creating Reusable Components with Directives [ 24 ] Beyond iterating, we might need to identify which is the first or the last element, what is its index number, and many other things. This can be achieved by using the following properties: Variable Type Details $index number Number of the element $first Boolean This is true if the element is the first one $last Boolean This is read more..

  • Page - 38

    Chapter 2 [ 25 ] The ngClick directive and other event directives The ngClick directive is one of the most useful kinds of directives in the framework. It allows you to bind any custom behavior to the click event of the element. The following code is an example of the usage of the ngClick directive calling a function: index.html <!doctype html> <html read more..

  • Page - 39

    Creating Reusable Components with Directives [ 26 ] </table> <input type="text" ng-model="car.plate" placeholder="What's the plate?" /> <button ng-click="park(car)">Park</button> </body> </html> In the preceding code, there is another pitfall. Inside the ngClick read more..

  • Page - 40

    Chapter 2 [ 27 ] The ngClass directive The ngClass directive is used every time you need to dynamically apply a class to an element by providing the name of the class in a data-binding expression. The following code shows the application of the ngClass directive: index.html <!doctype html> <html ng-app="parking"> <head> <title>[Packt] read more..

  • Page - 41

    Creating Reusable Components with Directives [ 28 ] <tr ng-class="{selected: car.selected}" ng-repeat="car in cars" > <td><input type="checkbox" ng- model="car.selected"/></td> <td><span read more..

  • Page - 42

    Chapter 2 [ 29 ] <script> var parking = angular.module("parking", []); parking.controller("parkingCtrl", function ($scope) { $scope.appTitle = "[Packt] Parking"; $scope.cars = []; $scope.colors = ["White", "Black", "Blue", "Red", read more..

  • Page - 43

    Creating Reusable Components with Directives [ 30 ] <td><span ng-bind="car.entrance"></span></td> </tr> </tbody> </table> <input type="text" ng-model="car.plate" placeholder="What's the plate?" /> <select read more..

  • Page - 44

    Chapter 2 [ 31 ] <thead> <tr> <th></th> <th>Plate</th> <th>Color</th> <th>Entrance</th> </tr> </thead> <tbody> <tr read more..

  • Page - 45

    Creating Reusable Components with Directives [ 32 ] Refactoring application organization As long as our application grows with the creation of new components such as directives, the organization of the code needs to evolve. As we saw in the Organizing the code section in Chapter 1, Getting Started with AngularJS, we used the inline style; however, now we will use the read more..

  • Page - 46

    Chapter 2 [ 33 ] <td><span ng-bind="car.color"></span></td> <td><span ng-bind="car.entrance"></span></td> </tr> </tbody> </table> </div> <div ng-hide="cars.length > 0"> The parking read more..

  • Page - 47

    Creating Reusable Components with Directives [ 34 ] car.entrance = new Date(); $scope.cars.push(car); delete $scope.car; }; }); Creating our own directives Now that we have already studied a bunch of built-in directives of a framework, it's time to create our own reusable components! First, we need to know how to register a new directive into our read more..

  • Page - 48

    Chapter 2 [ 35 ] template Imagine the number of times you have had the same snippet of the HTML code repeated over your application code. In the following code snippet, we are going to create a new directive with the code to reuse this: index.html <div alert></div> directives.js parking.directive("alert", function () { return { template: "<div read more..

  • Page - 49

    Creating Reusable Components with Directives [ 36 ] templateUrl There is another way to achieve the same goal with more quality. We just need to move the HTML snippet to an isolated file and bind it using the templateUrl property, as shown in the following code snippet: index.html <div alert></div> directives.js parking.directive("alert", function () { return { read more..

  • Page - 50

    Chapter 2 [ 37 ] The following code is the compiled directive without the original element: <div class="alert" alert=""> <span class="alert-topic"> Something went wrong! </span> <span class="alert-description"> You must inform the plate and the color of the car! </span> </div> restrict We attached our read more..

  • Page - 51

    Creating Reusable Components with Directives [ 38 ] Also, it is possible to combine more than one restriction at the same time by just using a subset combination of EACM . If the directive is applied without the restrictions configuration, it will be ignored by the framework. scope Our alert component is almost ready but it has a problem! The topic and the description read more..

  • Page - 52

    Chapter 2 [ 39 ] }, templateUrl: "alert.html", replace: true }; }); alert.html <div class="alert"> <span class="alert-topic"> <span ng-bind="topic"></span> </span> <span class="alert-description"> <span ng-bind="description"></span> </span> </div> The left-hand side contains read more..

  • Page - 53

    Creating Reusable Components with Directives [ 40 ] parking.directive("alert", function () { return { restrict: 'E', scope: { topic: '=topic', description: '=description' }, templateUrl: "alert.html", replace: true }; }); The last situation is when we need to execute something within the context of the parent scope. It could be read more..

  • Page - 54

    Chapter 2 [ 41 ] scope: { topic: '=topic', description: '=description', close: '&close' }, templateUrl: "alert.html", replace: true }; }); alert.html <div class="alert"> <span class="alert-topic"> <span ng-bind="topic"></span> </span> <span class="alert-description"> read more..

  • Page - 55

    Creating Reusable Components with Directives [ 42 ] transclude There are components that might need to wrap other elements in order to decorate them, such as alert , tab , modal , or panel . To achieve this goal, it is necessary to fall back upon a directive feature called transclude. This feature allows us to include the entire snippet from the view than just deal with read more..

  • Page - 56

    Chapter 2 [ 43 ] The next properties that we are going to study are considered more complex and reserved for advanced components. They are required every time we need to deal with the DOM or interact with other directives. These properties are link , require , controller , and compile . link Another important feature while creating directives is the ability to access the read more..

  • Page - 57

    Creating Reusable Components with Directives [ 44 ] </accordion-item> <accordion-item title="XYZ-9768"> Blue - 10/10/2002 11:10 </accordion-item> directives.html parking.directive("accordionItem", function () { return { templateUrl: "accordionItem.html", restrict: "E", scope: { title: "@" }, read more..

  • Page - 58

    Chapter 2 [ 45 ] Prefix Details (no prefix) This parameter locates the controller inside the current element. It throws an error if the controller is not defined within the require directive. ? This parameter tries to locate the controller, passing null to the controller parameter of the link function if not found. ^ This parameter locates the controller in the parent read more..

  • Page - 59

    Creating Reusable Components with Directives [ 46 ] title: "@" }, transclude: true, require: "^accordion", link: function (scope, element, attrs, ctrl, transcludeFn) { element.bind("click", function () { scope.$apply(function () { scope.active = !scope.active; read more..

  • Page - 60

    Chapter 2 [ 47 ] }; return { addAccordionItem: addAccordionItem, closeAll: closeAll }; } }; }); parking.directive("accordionItem", function () { return { templateUrl: "accordionItem.html", restrict: "E", scope: { title: "@" read more..

  • Page - 61

    Creating Reusable Components with Directives [ 48 ] Animation The framework offers a very interesting mechanism to hook specific style classes to each step of the life cycle of some of the most used directives such as ngRepeat , ngShow , ngHide , ngInclude , ngView , ngIf , ngClass , and ngSwitch . The first thing that we need to do in order to start is import the read more..

  • Page - 62

    Chapter 2 [ 49 ] This is quite a simple mechanism, but we need to pay careful attention in order to understand it. Animating ngRepeat The following code is a simple example where we will animate the enter event of the ngRepeat directive: app.css .ng-enter { -webkit-transition: all 5s linear; -moz-transition: all 5s linear; -ms-transition: all 5s linear; read more..

  • Page - 63

    Creating Reusable Components with Directives [ 50 ] Animating ngHide To animate the ngHide directive, we need to follow the same previous steps, however, using the .ng-hide-add and .ng-hide-add-active classes: app.css .ng-hide-add { -webkit-transition: all 5s linear; -moz-transition: all 5s linear; -ms-transition: all 5s linear; -o-transition: all 5s linear; read more..

  • Page - 64

    Chapter 2 [ 51 ] background-color: #FAFAD2 !important; } .selected-add-class { opacity: 0; } .selected-add-class-active { opacity: 1; } Here, we added the fade-in effect again. You are absolutely free to choose the kind of effect that you like the most! Summary Directives are a strong technology to support the creation of reusable components, thereby saving a lot of time read more..

  • Page - 65

    read more..

  • Page - 66

    Data Handling Most applications demand an intense development effort in order to provide a better interaction with its users. Bringing simplicity and usability is a huge challenge, and as our world is changing at the speed of the light, we must rely on a technology that really allows us to achieve this mission with the least amount of code and pain possible. In terms read more..

  • Page - 67

    Data Handling [ 54 ] The following code is an example that we have already seen before. Here, we are using it to retrieve the value of the car's plate, color, and entrance, and this is done inside the ngRepeat directive: index.html <table> <thead> <tr> <th></th> <th>Plate</th> read more..

  • Page - 68

    Chapter 3 [ 55 ] Sometimes, it might be necessary to transform the value of a given expression in order to exhibit it properly, however, without changing the underlying data. In the next section on filters, we will learn how expressions are well suited for this purpose. Filters Filters associated with other technologies, like directives and expressions, are responsible for the read more..

  • Page - 69

    Data Handling [ 56 ] Now, the output will be R$10.00 , which is the same as the previous output but prefixed with a different symbol. Although it seems right to apply just the currency symbol, and in this case the Brazilian Real (R$), this doesn't change the usage of the specific decimals and group separators. In order to achieve the correct output, in this case read more..

  • Page - 70

    Chapter 3 [ 57 ] type="text" ng-model="criteria" placeholder="What are you looking for?" /> <table> <thead> <tr> <th></th> <th>Plate</th> <th>Color</th> <th>Entrance</th> </tr> </thead> <tbody> <tr read more..

  • Page - 71

    Data Handling [ 58 ] The expected result if we use it based inside the car's list of our application is as follows: { "plate": "6MBV006", "color": "Blue", "entrance": "2013-12-09T23:46:15.186Z" } limitTo Sometimes, we need to display text, or even a list of elements, and it might be necessary to limit its size. This read more..

  • Page - 72

    Chapter 3 [ 59 ] orderBy With the orderBy filter, we can order any array based on a predicate expression. This expression is used to determine the order of the elements and works in three different ways: • String: This is the property name. Also, there is an option to prefix + or – to indicate the order direction. At the end of the day, read more..

  • Page - 73

    Data Handling [ 60 ] Color </a> </th> <th> <a href=""ng-click="field = 'entrance'; order=!order"> Entrance </a> </th> </tr> </thead> <tbody> <tr read more..

  • Page - 74

    Chapter 3 [ 61 ] Let's change our application by moving the date filter, which we used to display the date and hour separated in the view, to our controller: controllers.js parking.controller("parkingCtrl", function ($scope, $filter) { $scope.appTitle = $filter("uppercase")("[Packt] Parking"); }); This approach is often used when we need to transform the data before read more..

  • Page - 75

    Data Handling [ 62 ] Now, let's introduce a new parameter to give the users a chance to change the plate's separator: filters.js parking.filter("plate", function() { return function(input, separator) { var firstPart = input.substring(0,3); var secondPart = input.substring(3); return firstPart + separator + secondPart; }; }); Form validation Almost read more..

  • Page - 76

    Chapter 3 [ 63 ] <input type="text" name="plateField" ng-model="car.plate" placeholder="What's the plate?" /> </form> For the form, avoid using the name that has already been used inside the ngModel directive; otherwise, we will not be able to perform the validation properly. It would be nice to use read more..

  • Page - 77

    Data Handling [ 64 ] To finish, we can add a regular expression to validate the format of the plate. This can be done through the ngPattern directive: <input type="text" name="plateField" ng-model="car.plate" placeholder="What's the plate?" ng-required="true" ng-minlength="6" ng-maxlength="10" read more..

  • Page - 78

    Chapter 3 [ 65 ] Understanding the $pristine and $dirty properties Sometimes, it would be useful to know whether the field was never touched in order to trigger (or not) some validation processes. This can be done by the means of two objects with very suggestive names: $pristine and $dirty . Pristine means purity, and here, it denotes that the field wasn't touched by read more..

  • Page - 79

    Data Handling [ 66 ] <span ng-show="carForm.plateField.$error.pattern"> The plate must start with non-digits, followed by 4 to 7 numbers! </span> </alert> Summary In this chapter, we studied how AngularJS provides a complete set of features related to data handling, allowing the developers to easily present, transform, synchronize, read more..

  • Page - 80

    Dependency Injection and Services Cohesion is one of the most important and perhaps overlooked concepts of the object-oriented programming paradigm. It refers to the responsibility of each part of the software. No matter which component we talk about, every time it implements behavior different from its responsibilities, cohesion is degraded. Low cohesion applications contain plenty read more..

  • Page - 81

    Dependency Injection and Services [ 68 ] Dependency injection In order to create testable and well-designed applications, we need to take care about the way their components are related to each other. This relationship, which is very famous in the object-oriented world, is known as coupling, and indicates the level of dependency between the components. We need to be careful read more..

  • Page - 82

    Chapter 4 [ 69 ] Because of this, the most recommended way to use the dependency injection mechanism, despite verbosity, is through the inline array annotation, as follows: parking.controller("parkingCtrl", ["$scope", "$filter", function ($scope, $filter) { $scope.appTitle = $filter("uppercase")("[Packt] Parking"); }]); This way, no matter what the name of read more..

  • Page - 83

    Dependency Injection and Services [ 70 ] $scope.park = function (car) { car.entrance = new Date(); $scope.cars.push(car); delete $scope.car; }; $scope.calculateTicket = function (car) { $scope.ticket = parkingService.calculateTicket(car); }; }); Creating services with the factory The framework allows the creation of a service component in read more..

  • Page - 84

    Chapter 4 [ 71 ] In order to promote encapsulation, we need to use a function instead of an object literal, as follows: var car = function () { var plate = "6MBV006"; var color = "Blue"; var entrance = "2013-12-09T23:46:15.186Z "; }; Now, it's no longer possible to access any property of the object: > console.log(car.plate); undefined > read more..

  • Page - 85

    Dependency Injection and Services [ 72 ] return { plate: plate, color: color }; }(); Now, we are able to access the color but not the entrance of the car: > console.log(car.plate); 6MB006 > console.log(car.color); Blue > console.log(car.entrance); undefined Beyond that, we can apply another convention by prefixing the private members with _ , making the code read more..

  • Page - 86

    Chapter 4 [ 73 ] price: parkingPrice }; }; return { calculateTicket: _calculateTicket }; }); In our first service, we started to create some parking business rules. From now, the entrance hour is subtracted from the departure hour and multiplied by $10.00 to get the parking rate per hour. However, these rules were created by means of read more..

  • Page - 87

    Dependency Injection and Services [ 74 ] price: parkingPrice }; }; return { calculateTicket: _calculateTicket }; }); The framework also provides another kind of service called value. It's pretty similar to the constants; however, it can be changed or decorated. Creating services with the service There are other ways to create services read more..

  • Page - 88

    Chapter 4 [ 75 ] Creating services with the provider Sometimes, it might be interesting to create configurable services. They are called providers, and despite being more complex to create, they can be configured before being available to be injected inside other components. While the factory works by returning an object and the service with the constructor function, the read more..

  • Page - 89

    Dependency Injection and Services [ 76 ] In order to configure our provider, we need to use the config function of the Module API, injecting the service through its function. In the following code, we are calling the setParkingRate method of the provider, overwriting the default rate that comes from the parkingConfig method. config.js parking.config(function read more..

  • Page - 90

    Chapter 4 [ 77 ] Now, if we want to obtain a specific car, we need to add some parameters to this URL, and again, the lack of standard makes things harder: GET /retrieveCar?carId=10 HTTP/1.1 GET /getCar?idCar=10 HTTP/1.1 GET /giveMeTheCar?car=10 HTTP/1.1 Introduced a long time ago by Roy Fielding, the REST method, or Representational State Transfer, read more..

  • Page - 91

    Dependency Injection and Services [ 78 ] The following code shows an object literal after being converted into JSON through the JSON.stringify function: { "plate": "6MBV006", "color": "Blue", "entrance": "2013-12-09T23:46:15.186Z" } Also, the framework provides a built-in function called angular.toJson that does the same job of read more..

  • Page - 92

    Chapter 4 [ 79 ] AJAX AJAX, also known as Asynchronous JavaScript and XML, is a technology that allows the applications to send and retrieve data from the server asynchronously, without refreshing the page. The $http service wraps the low-level interaction with the XMLHttpRequest object, providing an easy way to perform calls. This service could be called by just passing a read more..

  • Page - 93

    Dependency Injection and Services [ 80 ] $scope.cars.push(car); delete $scope.car; }; $scope.calculateTicket = function (car) { $scope.ticket = parkingService.calculateTicket(car); }; var retrieveCars = function () { $http.get("/cars") .success(function(data, status, headers, config) { $scope.cars = data; read more..

  • Page - 94

    Chapter 4 [ 81 ] $scope.parkCar = function (car) { $http.post("/cars", car) .success(function (data, status, headers, config) { retrieveCars(); $scope.message = "The car was parked successfully!"; }) .error(function (data, status, headers, config) { switch(status) { read more..

  • Page - 95

    Dependency Injection and Services [ 82 ] }); }; retrieveCars(); }); Creating an HTTP facade Now, we have the opportunity to evolve our design by introducing a service that will act as a facade and interact directly with the backend. The mapping of each URL pattern should not be under the controller's responsibility; otherwise, it could generate a huge read more..

  • Page - 96

    Chapter 4 [ 83 ] updateCar: _updateCar, deleteCar: _deleteCar }; }); controllers.js parking.controller("parkingCtrl", function ($scope, parkingService, parkingHttpFacade) { $scope.appTitle = "[Packt] Parking"; $scope.colors = ["White", "Black", "Blue", "Red", "Silver"]; $scope.parkCar = function (car) { read more..

  • Page - 97

    Dependency Injection and Services [ 84 ] .error(function(data, status, headers, config) { switch(status) { case 401: { $scope.message = "You must be authenticated!" break; } case 500: { $scope.message = read more..

  • Page - 98

    Chapter 4 [ 85 ] After the header configuration, the request starts to send the custom header: GET /cars HTTP/1.1 Host: localhost:3412 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:29.0) Accept: application/json Accept-Language: pt-br,pt;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate The headers can also be configured through the configuration object of each request. It read more..

  • Page - 99

    Dependency Injection and Services [ 86 ] var timestamp = Date.now(); config.url = config.url + "?x=" + timestamp; return config; } } }); Something might happen with the request, causing an error. With the requestError interceptor, we can handle this situation. It is called when the request is rejected and can't be sent read more..

  • Page - 100

    Chapter 4 [ 87 ] Creating a single-page application In the past few years, the single-page application, also known as SPA, has been growing in popularity among frontend developers. It improves customers' experiences by not requiring the page to be constantly reloaded, taking advantage of technologies such as AJAX and massive DOM manipulation. Installing the module AngularJS read more..

  • Page - 101

    Dependency Injection and Services [ 88 ] Also, there is an otherwise function. It is called when the route cannot be matched against any definition. This configuration should be done through the config function of the Module API, as follows: config.js parking.config(function ($routeProvider) { $routeProvider. when("/parking", { templateUrl: read more..

  • Page - 102

    Chapter 4 [ 89 ] <link rel="stylesheet" type="text/css" href="css/app.css"> </head> <body> <div ng-view></div> </body> </html> parking.html <input type="text" ng-model="criteria" placeholder="What are you looking for?" /> <table> <thead> <tr> read more..

  • Page - 103

    Dependency Injection and Services [ 90 ] ng-model="car.selected" /> </td> <td><a href="#/car/{{car.id}}">{{car.plate}}</a></td> <td>{{car.color}}</td> <td>{{car.entrance | date:'dd/MM/yyyy hh:mm'}}</td> </tr> </tbody> </table> <form read more..

  • Page - 104

    Chapter 4 [ 91 ] <span ng-show="carForm.plateField.$error.maxlength"> The plate must have at most 10 characters! </span> <span ng-show="carForm.plateField.$error.pattern"> The plate must start with non-digits, followed by 4 to 7 numbers! </span> </alert> Passing parameters The route mechanism also allows us to pass read more..

  • Page - 105

    Dependency Injection and Services [ 92 ] {{car.plate}} <h5>Color</h5> {{car.color}} <h5>Entrance</h5> {{car.entrance | date:'dd/MM/yyyy hh:mm'}} <h5>Period</h5> {{ticket.period}} <h5>Price</h5> {{ticket.price | currency}} <button ng-click="depart(car)">Depart</button> <a href="#/parking">Back to parking</a> Changing the location There are many ways to read more..

  • Page - 106

    Chapter 4 [ 93 ] $window.location.href = "error.html"; }); }; retrieveCar($routeParams.id); }); Resolving promises Very often, the controller needs to resolve some asynchronous promises before being able to render the view. These promises are, in general, the result of an AJAX call in order to obtain the data that will be read more..

  • Page - 107

    Dependency Injection and Services [ 94 ] The same behavior could be obtained by means of the resolve property, defined inside the when function of the $routeProvider function with much more elegance, as follows: config.js parking.config(function ($routeProvider) { $routeProvider. when("/parking", { templateUrl: "parking.html", controller: read more..

  • Page - 108

    Chapter 4 [ 95 ] There are three events that can be broadcasted by the $route service and are very useful in many situations. The broadcasting mechanism will be studied in the next chapter, Chapter 5, Scope. The first event is the $routeChangeStart event. It will be sent when the routing process starts and can be used to create a loading flag, as follows: run.js read more..

  • Page - 109

    Dependency Injection and Services [ 96 ] Logging This service is very simple and can be used to create a logging strategy for the application that could be used for debug purposes. There are five levels available: • info • warn • debug • error • log We just need to inject this service inside the component in order to be able to log anything from it, read more..

  • Page - 110

    Chapter 4 [ 97 ] var result = []; angular.forEach(cars, function (car) { if (_matches(car, criteria)) { result.push(car); } }); resultCallback(result); }, 1000); }; var _matches = function (car, criteria) { return angular.toJson(car).indexOf(criteria) > read more..

  • Page - 111

    Dependency Injection and Services [ 98 ] return angular.toJson(car).indexOf(criteria) > 0; }; return { filter: _filter } }); Asynchronous with a promise-deferred pattern Nowadays, web applications are demanding increasingly advanced usability requirements, and therefore rely strongly on asynchronous implementation in order to obtain dynamic content from the backend, read more..

  • Page - 112

    Chapter 4 [ 99 ] if (result.length > 0) { successCallback(result); } else { errorCallback("No results were found!"); } }, 1000); }; var _matches = function (car, criteria) { return angular.toJson(car).indexOf(criteria) > 0; }; return { filter: _filter } }); read more..

  • Page - 113

    Dependency Injection and Services [ 100 ] The deferred API In order to create a new promise, we need to inject the $q service into our component and call the $q.defer() function to instantiate a deferred object. It will be used to implement the asynchronous behavior in a declarative way through its API. Some of the functions are as follows: • resolve(result) : read more..

  • Page - 114

    Chapter 4 [ 101 ] The promise API With the promise object in hand, we can handle the expected behavior of the asynchronous return of any function. There are three methods that we need to understand in order to deal with promises: • then (successCallback, errorCallback, notifyCallback) : The success callback is invoked when the promise is resolved. In the same way, error read more..

  • Page - 115

    read more..

  • Page - 116

    Scope The scope is an object that acts as a shared context between the view and the controller that allows these layers to exchange information related to the application model. Both sides are kept synchronized along the way through a mechanism called two-way data binding. In this chapter, we are going to cover the following topics: • Two-way data binding • Best read more..

  • Page - 117

    Scope [ 104 ] What happens when we change the plate and click on the button? Unfortunately, nothing. In order to reflect the changes on the plate, we need to implement the binding in the other direction, as shown in the following code snippet (in the render.js file): var plate = "AAA9999"; $("#plate").val(plate); $("#showPlate").click(function () { read more..

  • Page - 118

    Chapter 5 [ 105 ] This cycle is responsible for the notification process by looping over all the watchers, keeping them posted about any change that may occur in the scope. There are situations where we might need to invoke this mechanism manually by calling the $apply function directly, as follows: $scope.$apply(function () { $scope.car.plate = '8AA5678'; }); On the other read more..

  • Page - 119

    Scope [ 106 ] if (newValue == oldValue) return; $scope.plateCounter++; }); }); Best practices using the scope The scope is not the model itself—it's just a way to reach it. Thus, the view and controller layers are absolutely free to share any kind of information, even those that are not related to the model, and they only exist to fulfill specific read more..

  • Page - 120

    Chapter 5 [ 107 ] In the previous example, we changed the value of the dialog property directly from the ngClick directive declaration. The best choice in this case would be to delegate this intention to the controller and let it control the state of the dialog, such as the following code in the faq.html file: <button ng-click="openFAQ()">Open</button> read more..

  • Page - 121

    Scope [ 108 ] ng-model="username" placeholder="Username" /> <input type="password" ng-model="password" placeholder="Password"/> <button ng-click="login()">Login</button> </div> Consider the following code snippet in the controllers.js file: parking.controller("loginCtrl", function read more..

  • Page - 122

    Chapter 5 [ 109 ] Consider the following code snippet in the services.js file: parking.factory("loginService", function ($http) { var _login = function($scope) { var user = { username: $scope.username, password: $scope.password }; return $http.post('/login', user); }; return { login: _login }; }); Use read more..

  • Page - 123

    Scope [ 110 ] Consider the following code snippet of the services.js file: services.js parking.factory("loginService", function ($http) { var _login = function(user) { return $http.post('/login', user); }; return { login: _login }; }); Now, the login method will be invoked just by creating a user object, which is not coupled with the read more..

  • Page - 124

    Chapter 5 [ 111 ] When invoked, this function dispatches an event to all of its registered child scopes. In order to receive and handle the desired broadcast, $scope needs to call the $on function, thus informing you of the events you want to receive and also the functions that will be handling it. For this implementation, we are going to send the broadcast read more..

  • Page - 125

    Scope [ 112 ] Now, we need to start tickGenerator . This can be done using the run function of the module API, as shown in the following code snippet of the app.js file: parking.run(function (tickGenerator) { tickGenerator.start(); }); To receive the current date, freshly updated, we just need to call the $on function of any $scope object, as shown in the read more..

  • Page - 126

    Chapter 5 [ 113 ] Be aware that depending on the size of the application, the broadcast through $rootScope may become too heavy due to the number of objects listening to the same event. There are a number of libraries that implement the publish and subscribe pattern in JavaScript. Of them, the most famous is AmplifyJS, but there are others such as RadioJS, ArbiterJS, read more..

  • Page - 127

    read more..

  • Page - 128

    Modules As our application grows, we need to consider the possibility of splitting it into different modules. It comes with it a lot of advantages, thus helping us to find the best way to test and evolve each module separately from the others and also to share each module with other projects. In this chapter, we are going to cover the following topics: • How to read more..

  • Page - 129

    Modules [ 116 ] The UI module The UI module will contain the directives that we created in Chapter 2, Creating Reusable Components with Directives. To create an isolated and easy-to-use module, we should consider placing the entire code inside a unique file. However, this is not the kind of task that you would want to perform manually, and the best way to achieve this read more..

  • Page - 130

    Chapter 6 [ 117 ] Consider the following code snippet in the accordionDirective.js file: ui.directive("accordion", function () { return { restrict: "E", transclude: true, controller: function ($scope, $element, $attrs, $transclude) { var accordionItens = []; var addAccordionItem = function (accordionScope) { read more..

  • Page - 131

    Modules [ 118 ] }, template: "<div class='accordion-item'>" + "{{title}}" + "</div>" + "<div " + "ng-show='active' " + "class='accordion-description' " + "ng-transclude" + ">" + read more..

  • Page - 132

    Chapter 6 [ 119 ] deferred.resolve(result); } else { deferred.reject("No results were found!"); } }, 1000); return deferred.promise; }; var _matches = function (entity, criteria) { return angular.toJson(entity).indexOf(criteria) > 0; }; return { filter: _filter } }); read more..

  • Page - 133

    Modules [ 120 ] <script src="lib/search.js"></script> <!-- Application Scritps --> <script src="js/app.js"></script> <script src="js/constants.js"></script> <script src="js/controllers.js"></script> <script src="js/filters.js"></script> <script read more..

  • Page - 134

    Unit Testing Have you ever stopped to think about how much time we've spent just to understand and reproduce a defect? After this, we need to spend even more time looking for, between thousands of lines, the exact piece of the code that is causing this defect. Many times, the fastest, and perhaps the easiest step is fixing it. And what about manually testing the code read more..

  • Page - 135

    Unit Testing [ 122 ] The topics that we'll cover in this chapter are: • The Jasmine testing framework • Testing AngularJS components • Mocking with $httpBackend • Running tests with Karma The Jasmine testing framework Jasmine is an open source testing framework for the JavaScript language developed by Pivotal Labs. Its syntax is pretty similar to one of the most read more..

  • Page - 136

    Chapter 7 [ 123 ] Before writing the test, you should take care about the existing dependencies in your code. In this case, inside the _calculateTicket function, we are creating a Date object by calling the new operator. This kind of a situation should be avoided, otherwise you can't write an effective test. The following code considers the depart property inside the read more..

  • Page - 137

    Unit Testing [ 124 ] car.entrance = new Date(1401620400000); car.depart = new Date(1401649200000); var parkingService = parkingFactoryFunction(); var ticket = parkingService.calculateTicket(car); expect(ticket.period).toBe(8); expect(ticket.price).toBe(80); }); }); In order to execute our specification, let's check out Jasmine's built-in HTML-based read more..

  • Page - 138

    Chapter 7 [ 125 ] Services For now, let's create a service based on our parkingFactoryFunction function, as follows: parkingApp.js var parking = angular.module("parking", []); parkingService.js parking.factory("parkingService", function () { var _calculateTicket = function (car) { var departHour = car.depart.getHours(); var entranceHour = car.entrance.getHours(); read more..

  • Page - 139

    Unit Testing [ 126 ] parkingService = _parkingService_; })); it("Should calculate the ticket for a car that arrives any day at 08:00 and departs in the same day at 16:00", function () { var car = {place: "AAA9988", color: "Blue"}; car.entrance = new Date(1401620400000); car.depart = new Date(1401649200000); var ticket = read more..

  • Page - 140

    Chapter 7 [ 127 ] The expectations of the test should be done over the $scope object and not directly through the controller itself. This is very important because the view interacts with the controller through this shared object. Consider the following code snippet: parkingCtrlSpec.js describe("Parking Controller Specification", function () { var $scope; read more..

  • Page - 141

    Unit Testing [ 128 ] Filters Next, we are going to test filters. In the following code, there is the plate filter, which we developed in Chapter 3, Data Handling: plateFilter.js parking.filter("plate", function() { return function(input, separator) { var firstPart = input.substring(0,3); var secondPart = input.substring(3); return firstPart + separator read more..

  • Page - 142

    Chapter 7 [ 129 ] Directives The last kind of component that we are going to test is the directive. Let's start with one of the directives we created in Chapter 2, Creating Reusable Components with Directives, and converted it into a separated module in Chapter 6, Modules: uiApp.js var ui = angular.module("ui", []); alertDirective.js ui.directive("alert", function () { read more..

  • Page - 143

    Unit Testing [ 130 ] Creating the element with the directive The framework's compiler walks through the DOM, looking for elements that match the directives. In the following code is our directive before being compiled: <alert topic='Something went wrong!'> Please inform the plate and the color of the car </alert> Compiling the directive After this, the element is compiled read more..

  • Page - 144

    Chapter 7 [ 131 ] <span class="alert-description" ng-transclude=""> <span class="ng-scope"> Please inform the plate and the color of the car </span> </span> According to the steps that we just followed, you can understand how you can go from the raw element to the completed, compiled, and rendered directive. First, you need to read more..

  • Page - 145

    Unit Testing [ 132 ] '<span class="alert-description" ng-transclude="">' + '<span class="ng-scope">' + 'Please inform the plate and the color of the car' + '</span>' + '</span>' ; expect(element.html()).toBe(expectedElement); }); }); Mocking with $httpBackend The ngMock read more..

  • Page - 146

    Chapter 7 [ 133 ] getCar: _getCar, saveCar: _saveCar, updateCar: _updateCar, deleteCar: _deleteCar }; }); Inside each test, we defined the expected response to each request. It could be done through the $httpBackend service, as follows: parkingHttpFacadeSpec.js describe("Parking Http Facade Specification", function () { var parkingHttpFacade, read more..

  • Page - 147

    Unit Testing [ 134 ] $httpBackend.flush(); }); it("Should save a parked car", function () { var car = { plate: "AAA9977", color: "Green" }; $httpBackend.whenPOST("/cars").respond(function (method, url, data, headers) { var id = mockedCars.saveCar(angular.fromJson(data)); return read more..

  • Page - 148

    Chapter 7 [ 135 ] return [204, "", {}]; }); parkingHttpFacade.deleteCar(1).success(function (data, status) { expect(data).toBe(""); expect(status).toBe(204); expect(mockedCars.getNumberOfCars()).toBe(1); }); $httpBackend.flush(); }); }); Each response is configured through the respond function which read more..

  • Page - 149

    Unit Testing [ 136 ] var _saveCar = function (car) { return _cars.push(car); }; var _updateCar = function (id, car) { _cars[_id(id)] = car; } var _deleteCar = function (id) { _cars.splice(_id(id), 1); }; var _getNumberOfCars = function () { return _cars.length; } var _id = function (id) { return read more..

  • Page - 150

    Chapter 7 [ 137 ] $scope.park = function (car) { parkingHttpFacade.saveCar(car) .success(function (data, status, headers, config) { delete $scope.car; retrieveCars(); $scope.message = "The car was parked successfully!"; }) .error(function (data, status, headers, config) { read more..

  • Page - 151

    Unit Testing [ 138 ] At the moment, we have instantiated the controller, which calls the retrieveCars function and interacts with the parkingHttpFacade controller, thus aiming to interact with the backend and retrieve the cars. The park function also interacts with the facade in order to park a new car. Also, in case of any error, a property called message will read more..

  • Page - 152

    Chapter 7 [ 139 ] $httpBackend.whenGET("/cars").respond(function (method, url, data, headers) { return [500, mockedCars.getCars(), {}]; }); $httpBackend.flush(); expect($scope.message).toBe("Something went wrong!"); }); it("The car should be parked", function () { $httpBackend.whenGET("/cars").respond(function (method, url, data, read more..

  • Page - 153

    Unit Testing [ 140 ] <script src="lib/angular/angular.js"></script> <script src="lib/angular/angular-mocks.js"></script> <script src="js/parkingApp.js"></script> <script src="js/parkingCtrl.js"></script> <script src="js/plateFilter.js"></script> <script read more..

  • Page - 154

    Chapter 7 [ 141 ] After this, you can use the Node Package Manager, also known as npm. It will manage the installation of everything that we need to set up our environment, as follows: npm install –g karma Configuration The configuration is quite simple. It just requires a file called karma.conf.js , located in the root application directory. The best way to read more..

  • Page - 155

    Unit Testing [ 142 ] 'src/parkingCtrl.js', 'src/plateFilter.js', 'src/uiApp.js', 'src/alertDirective.js', 'src/mockedCarsFactoryFunction.js', 'src/parkingHttpFacade.js', 'src/parkingCtrlWithHttpFacade.js', 'spec/parkingServiceSpec.js', 'spec/parkingCtrlSpec.js', 'spec/plateFilterSpec.js', read more..

  • Page - 156

    Chapter 7 [ 143 ] Every time the autoWatch or singleRun property is enabled, you can use Karma just by using the karma start command. Summary In this chapter, we studied how to automate tests using Jasmine and Karma, adding productivity and quality to our development process. You learned how to create tests for each kind of component such as controllers, directives, read more..

  • Page - 157

    read more..

  • Page - 158

    Automating the Workflow Every time we perform the same activity over and over again, it can be considered waste, and we stand losing a great opportunity to automate it. Depending on the complexity of the workflow of our product, there are many steps that have to be performed, such as cleaning the temporary files from the last distribution, validating the code, concatenating read more..

  • Page - 159

    Automating the Workflow [ 146 ] Installation Just like Karma, Grunt requires NodeJS and the Node Package Manager to be installed. To proceed with the installation, we just need to type in the following command: npm install -g grunt-cli grunt After this, we are ready to configure it! Configuration The Gruntfile.js file is the JavaScript file that defines the read more..

  • Page - 160

    Chapter 8 [ 147 ] Creating a distribution package Before being ready for the production environment, you need to create an optimized distribution package of your product. This is very important for the following reasons: • Performance: Through the concatenation step, you could drastically reduce the amount of requests that the browser needs to perform every time the read more..

  • Page - 161

    Automating the Workflow [ 148 ] grunt.initConfig({ clean: { dist: ["dist/"] } }); grunt.loadNpmTasks("grunt-contrib-clean"); grunt.registerTask("dist", ["clean"]); } In this case, we are creating our distribution package inside the dist/ directory; however, you are free to choose another directory. 2. read more..

  • Page - 162

    Chapter 8 [ 149 ] 3. Concatenating step: The concatenation step, done by the grunt-contrib- concat plugin, concatenates the configured source files inside a single destination file. This plugin can be installed with the following command: npm install grunt-contrib-concat --save-dev In order to configure it, we need to inform the source files and the destination file through read more..

  • Page - 163

    Automating the Workflow [ 150 ] grunt.initConfig({ clean: { dist: ["dist/"] }, jshint: { dist: ['Gruntfile.js', 'js/**/*.js', 'test/**/*.js'] }, concat: { dist: { src: ["js/**/*.js"], dest: "dist/js/scripts.js" } }, read more..

  • Page - 164

    Chapter 8 [ 151 ] dist: ["dist/"] }, jshint: { dist: ['Gruntfile.js', 'js/**/*.js', 'test/**/*.js'] }, concat: { dist: { src: ["js/**/*.js"], dest: "dist/js/scripts.js" } }, uglify: { dist: { read more..

  • Page - 165

    Automating the Workflow [ 152 ] grunt.initConfig({ clean: { dist: ["dist/"] }, jshint: { dist: ['Gruntfile.js', 'js/**/*.js', 'test/**/*.js'] }, concat: { dist: { src: ["js/**/*.js"], dest: "dist/js/scripts.js" } }, read more..

  • Page - 166

    Chapter 8 [ 153 ] 7. Running step: The last and optional step is about running the application after the distribution package is built. Grunt has a web server plugin called grunt-connect , and we just need to type in the following command to install it: npm install grunt-contrib-connect --save-dev After this, we need to configure at least the base directory of the read more..

  • Page - 167

    Automating the Workflow [ 154 ] dist: { options: { port: 9001, base: 'dist/' } } } }); grunt.loadNpmTasks("grunt-contrib-clean"); grunt.loadNpmTasks("grunt-contrib-jshint"); grunt.loadNpmTasks("grunt-contrib-concat"); read more..

  • Page - 168

    Chapter 8 [ 155 ] With the package.json file created, we can install the plugins just by typing in the following command: npm install This is very useful when we share the project with other developers, thus avoiding the installation of each plugin separately. Executing the workflow In order to execute any specific task or even the entire workflow, we just need to read more..

  • Page - 169

    Automating the Workflow [ 156 ] }, lib: { src: ["lib/**/*.js"], dest: "dist/lib/lib.js" } } After this, you can run all the configurations by calling the task directly, as follows: grunt concat Or call any specific task by using a colon, as follows: grunt concat:js grunt concat:lib Managing packages with Bower Bower is a package read more..

  • Page - 170

    Chapter 8 [ 157 ] Installing packages After finding the desired package, you just need to execute the following command in order to download and install it: bower install <package name> To install the package, you just need to use this command with the package name as follows: bower install angular --save The angular package will be downloaded from its Git repository read more..

  • Page - 171

    Automating the Workflow [ 158 ] Cache The removed packages will be stored cached inside Bower's cache, located in the cache/bower directory inside the user's home folder. You can retrieve the list of cached packages using the following command: bower cache list Bower also allows for offline package installation, just in case we do not have an Internet connection and need read more..

  • Page - 172

    Index Symbols $apply function 104 $broadcast function 110 $compile service 130 $digest function 130 $dirty object 65 $emit function 112 $error object 65 $filter service 128 $httpBackend service mocking with 132-139 $logProvider event 96 $on function 111 $pristine object 65 $rootScope object 110 $routeProvider function 87 $timeout service levels 96, 97 $watch function read more..

  • Page - 173

    [ 160 ] directives 129 filters 128 service 125 testing 124 test, running with Karma 140 application organization refactoring 32 architectural concepts, AngularJS controller 9 framework, setting up 10, 11 model 9 view 9 array, orderBy filter 59 Asynchronous JavaScript and XML (AJAX) 79, 80 autoWatch property 142 B backend communication about 76 AJAX 79 read more..

  • Page - 174

    [ 161 ] link function, calling with scope 130 testing 129 directive scope configuring 38 distribution package creating, for performance improvement 147 creating, for quality improvement 147 creating, for security improvement 147 grunt-connect plugin, installing 153-155 grunt-contrib-clean plugin, installing 147, 148 grunt-contrib-concat plugin, installing 149 grunt-contrib-copy read more..

  • Page - 175

    [ 162 ] installation, Grunt 146 installation, grunt-connect plugin 153-155 installation, grunt-contrib-clean plugin 147, 148 installation, grunt-contrib-concat plugin 149 installation, grunt-contrib-copy plugin 150 installation, grunt-contrib-uglify plugin 149 installation, grunt-karma plugin 151 installation, packages Bower used 157 interceptors httpTimestampInterceptor 85 read more..

  • Page - 176

    [ 163 ] O one-way data binding mechanism 103 orderBy filter about 59, 60 array 59 function 59 string property 59 P package.jsonfile file 146, 154, 155 packages installing, with Bower 157 managing, with Bower 156 searching, with Bower 156 using 157 parking application module 115, 119, 120 Plain-Old-JavaScript-Object (POJO) 9 POST method 77 prerequisites, Karma read more..

  • Page - 177

    [ 164 ] two-way data binding $apply function 104 $watch function 105 about 24, 103, 104 U UI module 115-118 update command 157 uppercase filter 60 V value service 74 W workflow automating, with Grunt 145 executing 155 World Wide Web (WWW) 7 uploaded by [stormrg] read more..

  • Page - 178

    Thank you for buying AngularJS Essentials 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 professionals in read more..

  • Page - 179

    Dependency Injection with AngularJS ISBN: 978-1-78216-656-6 Paperback: 78 pages Design, control, and manage your dependencies with AngularJS dependency injection 1. Understand the concept of dependency injection. 2. Isolate units of code during testing JavaScript using Jasmine. 3. Create reusable components in AngularJS. AngularJS Directives ISBN: 978-1-78328-033-9 read more..

  • Page - 180

    Mastering Web Application Development with AngularJS ISBN: 978-1-78216-182-0 Paperback: 372 pages Build single-page web applications using the power of AngularJS 1. Make the most out of AngularJS by understanding the AngularJS philosophy and applying it to real-life development tasks. 2. Effectively structure, write, test, and finally deploy your application. read more..

Write Your Review