AngularJS Best Practices Guide
angularjs_best_practices_guide
User Manual: Pdf
Open the PDF directly: View PDF .
Page Count: 68
Download | |
Open PDF In Browser | View PDF |
AngularJS Best Practices Guide Copyright Information 2017. SecureAuth© is a copyright of SecureAuth Corporation. SecureAuth’s IdP software, appliances, and other products and solutions, are copyrighted products of SecureAuth Corporation. June, 2017 For information on supporting this product, contact your SecureAuth sales representative: Email: support@secureauth.com Phone: +1.949.777.6959 or +1-866- 859-1526 Website: https://www.secureauth.com/Support.aspx Contents Introduction 1 Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 Software Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 SecureAuth-Specific Workflow 3 New ‘Data-View’ Attribute . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Bootstrap and New Themes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 GulpJS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Sass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Themes-Master Scaffold Overview and Structure. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 Views . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 App.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 Creating a New Theme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 AngularJS Overview 9 Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 Properties at Runtime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 AngularJS Best Practices Guide Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Directive Behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Directives and CSS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Data Binding Expression. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 View, Controller, and Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 $scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Config Phase Components . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Routing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Working with Routing in a Local Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 Views. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Factories. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 AJAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 RESTful . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 AJAX + RESTful . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 $resource . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 AngularJS Animations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 Animation Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Compiling/Deploying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 Troubleshooting Compiling and Deploying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 Test Driving a Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .40 QUnit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .40 Common Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Styling Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Text Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Function Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Adding a New Element or Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 GitHub Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Reproducing a Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 GULP tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Route Object: Resolving Property . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 View Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Load Dependencies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Questions and Answers 55 Best Practices 57 MVC Flow. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Large Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 AngularJS Best Practices Guide Factory Methods. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Module Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Controllers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Dependency Annotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 $Inject Property Annotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Implicit Annotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 Strict Dependency Injection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 ‘willBreak’ Service. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Declarative Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 Large AngularJS Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 References 63 Introduction AngularJS is a structural framework for dynamic web applications that extends the HTML vocabulary resulting in an expressive and readable markup. It offers a toolset for building web pages that goes beyond the static structures allowed by white-bread versions of HTML. While HTML enables the designer to create web pages replete with text, pictures, and links, it has little flexibility when it comes to dynamic logic and workflow. AngularJS extends the HTML vocabulary to accommodate many more techniques and strategies, including the very techniques SecureAuth uses for authenticating users. AngularJS is fully extensible and works well with other libraries. Every feature can be modified or replaced to suit your unique development workflow and feature needs. Benefits + Easy customization of HTML markup, CSS, and JS + HTML5 syntax and API feature sets + AngularJS to extend HTML vocabulary resulting in an extraordinarily expressive, readable, and quick to develop workflow + + + + One framework for every device with Bootstrap + + + + + + Out-of-band patch and fix Automate and enhance workflow with Gulp SASS for CSS preprocessor Available documentation for common HTML elements, dozens of custom HTML and CSS components, and helpful JS plug-ins Use of modular page components Allow us to move some of our view logic from the back-end to the front-end Not difficult to learn Create powerful front-end themes quickly Useful for single-page applications Single-page applications (SPAs) are web applications that fit on a single web page. They are essentially desktop apps, like Google maps, designed to be used on all devices. Each HTML page contains mini-views (HTML fragments) that can be loaded in the background. There is no reloading of the page and requires handling of browser history, navigation, and bookmarks. The purpose of this guide is not to instruct you in the use of AngularJS, since many tutorials are available online to provide that service, but to show you how SecureAuth uses this framework and has enhanced its basic HTML vocabulary for designing web pages within the SecureAuth IdP environment. Introduction 1 AngularJS Best Practices Guide This guide is divided into sections that discuss these major topics: + + + + + + + Structure Compiling and Deploying Troubleshooting Common Changes GULP tools SecureAuth-specific Directives Advanced Strategies Software Requirements In addition to your normal programming applications, you should make sure the following programs are installed: + AngularJS + GULP + GitHub Introduction 2 AngularJS Best Practices Guide SecureAuth-Specific Workflow This section includes a brief discussion of those topics and tools most important to SecureAuth programming concerns. Of paramount importance are the tools in AngularJS required to create the dialog boxes and prompts that Tailoring Frontline programmers utilize most often to design the SecureAuth IdP SSO screens for a new customer. The essential topics and tools in this workflow are: + + + + + New ‘Data-View’ Attribute Bootstrap and New Themes GulpJS Sass Themes-Master Scaffold Overview and Structure New ‘Data-View’ Attribute The data-view attribute value determines what view HTML will render, as shown in this example: Each view HTML will indicate what directives to modify. SecureAuth-Specific Workflow 3 AngularJS Best Practices Guide Bootstrap and New Themes Bootstrap makes front-end web development faster and easier. One code base is used for every device with CSS media queries. The reasons we are using Bootstrap are: + Increase speed of development by utilizing ready-made blocks of code with cross-browser compatibility and CSS functionality. + Ensures consistency regardless of who’s working on the project. + Framework takes into account the future of design and development with HTML5 and CSS3 + A great aspect of bootstrap is that you can make it your own. You can sit down and go through the whole framework and keep what you need and ditch what you don’t. GulpJS We recommend the use of GulpJS for your streaming build system. By using a node’s stream file, manipulation is all done in memory and a file is not written until you tell it to do so. It is the streaming nature that enables GulpJS to pipe and pass around the data being manipulated or used by plugins. These plugins are only intended to do one job at a time, so it is not uncommon to pass a singular file through multiple plugins. For more on GulpJS, refer to http://gulpjs.com/. Sass Sass (syntactically awesome stylesheets) is a ‘pre-processing’ scripting language that extends CSS by allowing developers to write code in one language and then compile it into CSS. Sass is an extension of CSS3, adding nested rules, variables, mix-ins, selector inheritance, and more. We recommend the use of this extension in order to provide greater latitude to style choices for SecureAuth presentation pages. Themes-Master Scaffold Overview and Structure After installation of the AngularJS applications, the essential theme files and folders structure under 2016 Light resemble the example in Figure 1. SecureAuth-Specific Workflow 4 AngularJS Best Practices Guide FIGURE 1. 2016 Light Theme Files and Folders Structure To program a new theme, specify the theme in the ‘Themes’ folder. If needed, copy or clone a new theme from the available themes. (The ‘dist’ folder includes the compiled version of the theme.) For example, when the 2016 Light element is expanded, a screen like Figure 2 appears. SecureAuth-Specific Workflow 5 AngularJS Best Practices Guide FIGURE 2. 2016 Light Element Expansion Example The elements in the Themes-Master folder include: + + + + + directives – modular components views – layout base on the state view app.min.js – main application JavaScript (see page 38) MFAStylesSheet.css – main application CSS theme.js – helper/custom JavaScript Directives Directives are organized by states and provide the HTML within each directive tags. Directives are annotated in the following manner: {{directive}}.html In HTML, you will see native angular directives such as ‘ng-if’ or ‘ng-repeat’. These are documented in https://docs.angularjs.org/api/ng/directive and provide basic display logic. (Some of the most important directives are briefly described later in this guide.) Directives can also contain the logic localized to all directive tags. That is, {{directive}}.directive.js Directive logic follows this syntax: 'use strict'; angular.module('secureauth') SecureAuth-Specific Workflow 6 AngularJS Best Practices Guide .directive('{directive}', function (config, {service}) { var {directive}Controller = function () { var vm = this; angular.extend(vm, { // Objects }); }; return { restrict: 'EA', controller: {directive}Controller, controllerAs: '{directive}', templateUrl: config.theme + '/directives/{currentState}/{directive}/ {directive}.html', bindToController: true }; }); Common directives that are used in many states are contained in the /common folder. For more on directives, refer to “Directives” starting on page 11. Services Services are organized based on state. These services are used by directives to get the aspgenerated objects in order to regenerate it in the design that the theme will specify. Services include: + domModel.js – this service contains the logic that parses html dom objects and builds new objects used by this angular theme engine to rebuild those same objects within the theme design. These functions are called throughout the services. + App.scss – this service contains the main stylesheet. It is compiled during “gulp theme:build” to MFAStyleSheet.css. See http://sass-lang.com/guide for documentation on SCSS syntax and usage. For more on this topic, refer to “Services” starting on page 27. Views Views are organized by states and provide the HTML shell for each state. Each state HTML contains directive tags or custom angular generated by HTML tags. For more on this, refer to “Views” starting on page 27. SecureAuth-Specific Workflow 7 AngularJS Best Practices Guide App.js The app.js file in the ‘dist’ folder contains the aggregated results of combining the JS files you compiled in your gulp file. It defines and initializes the module. Among other features, the app.js file determines what state the current application is in. This includes + ServerState – get the state from the ‘data-view’ attribute in the head + RenderState – parse MLALoginControl data to get current state + PathState – get state from URL Creating a New Theme New themes can be created by right-clicking on an existing theme element and selecting the clone option. Once cloned, rename the cloned theme as needed. The file structure and its required elements are populated for the new theme. SecureAuth-Specific Workflow 8 AngularJS Best Practices Guide AngularJS Overview This section includes a more exhaustive run-down on the language itself: the objects and arguments most critical to using AngularJS. FIGURE 3. AngularJS Basic Flow Structure AngularJS as used in SecureAuth webpage theme creation includes the following structural elements: + App.js + Views + Directives Each of these essential elements are discussed on the following pages. Objects Every component within AngularJS is an object including functions and arrays. Objects include both properties and methods. These are presented as: + A collection of name-value pairs AngularJS Overview 9 AngularJS Best Practices Guide + Names are strings + Values can be anything + Properties and methods can be added at runtime Objects can inherit other objects as in this example: var customer = {name: “Jack”, gender: “male”}; var circle1 = {radius: 9, getArea: someFunction}; var circle2 = { radius: 9, getRadius: function() { return this.radius; } } Properties at Runtime One of the simplest ways to create objects is to use an argument like this example: + One of the simplest ways to create an object is: var obj - new Object(); obj.x = 10; obj.y = 12; obj.method = function() {...} + This adds at runtime two properties to the obj: - object! + The object is built-in data type This adds two properties at runtime to the obj – object. The object is built as a data type. Class You can create constructor-function in JavaScript in this manner: function Point() { this.x - 1; this.y - 1; } var p = new Point(); An example of the correct use of properties and classes is shown in the following example: function Circle(radius) { AngularJS Overview 10 AngularJS Best Practices Guide this.radius = radius; this.getArea = function(); { return (this.radius * this.radius) * Math.PI; }; } var myobj = new Circle(5); document.write(myobj.getArea() ); Functions Every function in JS is a Function object and perform these operations: + Can be passed as arguments + Can store name / value pairs + Can be anonymous or named The usage of certain functions may prove ineffective or inefficient. For example: var myfunction = new Function(“a”,”b”, “return a+b;”); print(myfunction(3,3) ); Functions can take other functions as arguments. For example: -fetchUrl ( onSuccess, onError ) You can use such anonymous functions in this manner: -fetchUrl( function() (…), function() (…) ); Directives Directives apply special behavior to attributes or elements in HTML. AngularJS directives allow the developer to specify custom and reusable HTML-like elements and attributes that define data bindings and the behavior of presentation components. Some of the most common SecureAuth-derived directives are shown in Table 1. TABLE 1. SecureAuth-Derived Directives Directive Meaning ng-app Declares the root element of an AngularJS application under which directives can be used to declare bindings and define behavior. AngularJS Overview 11 AngularJS Best Practices Guide TABLE 1. SecureAuth-Derived Directives Directive Meaning ng-bind Replaces the text content of the specified HML with the value of given expression Sets the text of a DOM element to the value of an expression. For example, displays the value of ‘name’ inside the span element. Any change to the variable ‘name’ in the application's scope reflect instantly in the DOM. ng-model Stores/updates the value of the input field into a variable Similar to ng-bind, but establishes a two-way data binding between the view and the scope. ng-model-options Provides tuning for how model updates are done. ng-class Enables class attributes to be dynamically loaded. ng-controller Specifies a JavaScript controller class that evaluates HTML expressions. ng-repeat Instantiate an element once per item from a collection. ng-show ng-hide Conditionally shows or hides an element, depending on the value of a Boolean expression. Show and hide is achieved by setting the CSS display style. ng-switch Conditionally instantiates one template from a set of choices, depending on the value of a selection expression. ng-view Handles routes that resolve JSON before rendering templates driven by specified controllers. ng-if Allows the display of the element that follows, if the conditions are true. When the condition is false, the element is removed from the DOM. When true, a clone of the compiled element is re-inserted. ng-aria Enables accessibility support for common ARIA attributes. ng-animate Provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives. Since ng-* attributes are not valid in HTML specifications, data-ng-* can also be used as a prefix. For example, both ng-app and data-ng-app are valid in AngularJS. For example, the correct use of both the Ng-init and Ng-repeat directives is shown below:Title AngularJS Overview 12 AngularJS Best Practices GuideDirective Behavior Prevailing behavior with directives should include limiting DOM manipulation. This involves aggressively restricting all DOM access (which usually translates to all jQuery usage) to a thin “segregation layer”. Everything outside of the segregated DOM layer can be tested rapidly in isolation from the browser using a lean JavaScript engine such as node.js. Directives and CSS Cascading Style sheets (CSS) work seamlessly with directives, following this simple rule: TABLE 2. Directives and CSS Interrelationship Event Starting CSS Ending CSS Directives Enter .ng-enter .ng-enter-active ngRepeat, ngInclude, ngif, ngView Leave .ng-leave .ng-leave-active ngRepeat, ngInclude, ngif, ngView Move .ng-move .ng-move-active ngRepeat An example of this usage is shown below: /* starting animation */ .ng-enter { -webkit-transition: 1s; transition: 1s; margin-left: 100%; } /* ending animation */ .ng-enter-active { margin-left: 0; } /* starting animation */ .ng-leave { AngularJS Overview 13 AngularJS Best Practices Guide -webkit-transition: 1s; transition: 1s; margin-left: 0; } /* ending animation */ .ng-leave-active { margin-left: 100%; } Another example of the use of directive as a function is shown below: angular.module(‘contactWorks.directives’); directive(‘focus’, [function () { return { restrict; ‘A’; link: function (scope, iElement, iAttrs) { iElement.focus(); } } }]); Filters Filters are used to filter the output:Cool loop!
- {{name}}
AngularJS Overview 14 AngularJS Best Practices Guide For instance, you might choose to filter the output by order (orderBy), as in this example: Filters format the output such as formatting for currency, numbers, date, and lowercase. An example of the correct use of a filter is shown in the following example: AngularJS Overview 15 AngularJS Best Practices Guide Another example shows the use of a filter when using user input filters: Another example of HTML using a filter is shown here: This uses the ng-app directive to define an app and filters it. Yet another example of a filter is shown in this example: AngularJS Overview 16 AngularJS Best Practices Guide Expressions Angular expressions are JavaScript-like code snippets usually placed in bindings like this: -{{ expression }} Valid Expressions in AngularJS include: -{{ 1+2 }} {{ a+ b }} -{{ items[index] }} Filters are used to format or filter data in this manner: AngularJS Overview 17 AngularJS Best Practices Guide A valid HTML 5 Example is: Templates Templates are HTML code with additional markup, directives, expressions, filters, and other components as shown in this example: Data Binding Expression This concept binds a model to a View using the expression wrapper {{ AngularJS Overview }}. 18 AngularJS Best Practices Guide When used with directives, data binding can prove powerful, as in this example: Two-way data binding is an effective tool for linking a view to a model. FIGURE 4. Two-Way Data Binding AngularJS Overview 19 AngularJS Best Practices Guide View, Controller, and Scope As indicated in Figure 5, there is an implicit linkage between view, controller, and scope in AngularJS. FIGURE 5. View, Controller, and Scope Linkage $scope $scope is an object that links the controller to the view. AngularJS invokes the constructor with a $scope object and runs inside ng-app (div). Put in the context of code, the $scope intermediary can be used to link view with controller as in the following example: // Angular will inject the $scope object, you don’t have to // worry about it function NumberCtrl ($scope) { // $scope is bound to view, so the communication // to view is done using the $scope $scope.number = 1; $scope.showNumber = function showNumber() { window.alert ( “your number = “ + $scope.number ); }; } WARNING: $scope will not work for AngularJS 1.3 or earlier. Only versions later than AngularJS 1.3 use $scope in this manner. AngularJS Overview 20 AngularJS Best Practices Guide An example of the use of the ng-app wrapper to define the controller implemented in controller.js is shown in the following example: When $scope is used to link the controller to a view, one of these conditions must occur: + Setup the initial state of $scope object + Add behavior to the $scope object Do not use a controller when one of these conditions occurs: + + + + Manipulating the DOM (use data binding and/or directives) Formatting output (using form controls) Filtering the output (using filters0) Sharing code or state (using services) A template for a controller is shown in the following example: // Create new module ‘myApp’ using the angular.module method // The module is not dependent on any other module var myModule = angular.module()’myModule’, []); myModule.controller( ‘MyCtrl’, function ($scope) { // Your controller code here: }); AngularJS Overview 21 AngularJS Best Practices Guide The definition of a controller can then be used to construct a module as discussed in the following topic. Modules A module is a reusable container for different features of your app such as controllers, services, filters, and directives as shown in Figure 6. FIGURE 6. Module Container AngularJS Overview 22 AngularJS Best Practices Guide Yet another arrangement of a module object is shown in Figure 7. FIGURE 7. Module Object Flow Chart Modules can be loaded in any order. You can build our own filters and directives. NOTE: If you have defined many controllers, you might be polluting JS namespace. Be judicious in your use of these objects. An example of a module and its use is shown in the following example: // declare a module var myAppModule = angular.module(‘myApp’, []); // configure the module // in this example we will create a greeting filter myAppModule.filter(‘greet’, function() { return function(name) { return ‘Hello,’ + name + ‘!’; ); }); To create a controller in a module, use a structure like the following example: var myModule = angular.module(‘myModule’, []); myModule.controller(‘MyCtrl’, function($scope) { var model = { “firstname”; “Jack”, AngularJS Overview 23 AngularJS Best Practices Guide “lastname”; “Smith”}; $scope.model = model; $scope.click = function() { alert($scope.model.firstname); }; }); This then contributes to creating a module object as shown in the following example: Modules can also be used as dependencies as in the following example: angular.module(‘myApp,[‘ngRoute’, ‘myApp.filters’, ‘myApp.services’, ‘myApp.directives’, ‘myApp.controllers’, ‘ngRoute’, ‘ngResource’, ‘ui.bootstrap’, ]) AngularJS Overview 24 AngularJS Best Practices Guide Config Phase Components Components register against the module in the config phase using providers. For example, to register a controller manually use $controllerProvider in this manner: angular.module(‘moduleName’,[]) .config(function($controllerProvider){ $controllerProvider.register(‘Ctrl’,function() { //controller code }) }); For more on providers, refer to “Providers” on page 30. Routing Routing is useful particularly when building a SPA app because everything can be handled on a single page. The use of routing can address several questions: + How should back-buttons work? + How do I link between “pages”? + How about URLs? For example, you can link several operations in this manner: A specific directive is used for this purpose: ngRoute. AngularJS Overview 25 AngularJS Best Practices Guide //This module is dependent on ngRoute. Load ngRoute before this var myApp = angular.module(‘myApp’, [‘ngRoute’]); //Configure routing myApp.config(function($routeProvider) { // Usually we have different controllers for different views // In this demonstration, the controller does nothing $routeProvider.when(‘/’, { templateUrl: ‘view1.html’, controller: ‘MySimpleCtrl’ }); $routeProvider.when(‘/view2’, { templateUrl: ‘view2.html’, controller: ‘MySimpleCtrl’ }); $routeProvider.otherwise({ redirectTo: ‘/’ });\ }); //Now add a new controller to MyApp myApp.controller(‘MySimpleCtrl’, function ($scope) { }); However, as shown in the previous example, ngRoute must be loaded before an argument like this can be made. Working with Routing in a Local Environment If you are returned the message “cross origin requests are only supported for HTTP”, this means either + You should disable web security in your browser + Or you should use a web server and access files http://... To disable web security in Chrome from the run prompt, enter: Taskkill /F /IM chrome.exe where chrome.exe is located at: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe and possible switches are: --disable-web-security and --allow-file-access-from-files AngularJS Overview 26 AngularJS Best Practices Guide Views A view is an HTML fragment and can be expressed as shown in the following example: + view1.html:{{ ‘World’ | greet }}View 1
+ view2.htmlView 2
Services View-independent business logic should not be in the controller; it should be relegated to a service component. AngularJS Overview 27 AngularJS Best Practices Guide Controllers are view-specific whereas services are application-specific. FIGURE 8. Controllers vs. Services Move from view to view and service is still alive. The controller’s responsibility is to bind the model to a view. The model can be fetched from service but the controller is not responsible for manipulating (create, destroy, update) the data. In many cases, rather than using $scope to link views to controllers, it may prove more useful to specify controller using a service instead. AngularJS has many built in services; for example, $http (for a full discussion of services, see the online discussion at http://docs.angularjs.org/api/service). An example of adding a new controller using a service, is shown in the following example: // Add a new controller to MyApp. This controller uses Service. myApp.controller(‘ViewCtrl’, function($scope, CustomerService) { $scope.contacts = CustomerService.contacts; }); // Add a new controller to MyApp. This controller uses Service. myApp.controller(‘ModifyCtrl’, function($scope, CustomerService) { $scope.contacts = CustomerSerivce.contacts; }); // Create a factory object that contaoins services for the controllers myApp.factory(‘CustomerService’, function() { var factory = (); factory.contact5s = ( {name: “Jack”, salary: 3000}, {name: “Tina”, salary 5000}, {name: “John”, salary: 4000}); return factory; AngularJS Overview 28 AngularJS Best Practices Guide Another use of a service is shown in this example: // Service is instantiated with new keyword // Service function can use “this” and the return value is this. myApp.service(‘CustomerService’, function() { this.contacts = [ {name: “Jack”, salary: 3000}, [ {name: “Tina”, salary: 5000}, [ {name: “John”, salary: 4000}, }); As an alternative to a service, you might choose to select and define one or more factories as discussed in the next topic. Factories Factories are a reasonable alternative to services. FIGURE 9. Factories Component AngularJS Overview 29 AngularJS Best Practices Guide The differences between services and factories can be summed up in the following example: In general, if you want your function to be defined as a normal function, use factory. If you want your function to be instantiated with a new operator, use service. Providers A Provider is yet another type of function to consider when constructing an AngularJS argument. FIGURE 10. Providers Component AngularJS Overview 30 AngularJS Best Practices Guide In general, the features of providers, services, and factories are compared in Table 3. TABLE 3. Providers, Services, and Factories Comparison Features Factory Service Value Constant Provider Can have dependencies yes yes no no yes Object available in config phase no no no yes yes Can create functions/primitives yes no yes yes yes AJAX Asynchronous JavaScript + XML (AJAX) is used only occasionally, since XML is rarely needed; more often the code of choice is JSON. However, when used, AJAX can be implemented to send and retrieve data asynchronously from server in background. There are a group of technologies that use this asynchronous version, including HTML, CSS DOM, XML/JSON, XMLHttpRequestobject, and JavaScript. An example of using AJAX is: RESTful Web Service APIs that adhere to REST architecture constraints are known as RESTful APIs. These constraints are: + Base URI, such as https://www.example/resources AngularJS Overview 31 AngularJS Best Practices Guide + Internet media type for data such as JSON or XML + Standard HTTP methods: GET, POST, PUT, DELETE + Links to reference (such as Reference state and Related resources) RESTful API HTTP methods are shown in Table 4. TABLE 4. RESTful API HTTP Methods Resource GET PUT POST DELETE Collection URI such as http://example.com/ resources List the URIs and other details of the collections members Replace the entire collection with another collection Create a new entry in the collection. The new entry’s URI is assigned automatically and is usually returned by operation Delete the entire collection Element URI, such as http://example.com/ resources/item1? Retrieve a representation of the collection’s addressed member, expressed in an appropriate internal media type Replace the collection’s addressed member; if it doesn’t exist, create it Not generally used. Delete the collection’s addressed member Treat a collection’s addressed member in its own right, and create a new entry of it AJAX + RESTful A hybrid form of AJAX and RESTful creates a syntax that can prove useful in specific situations. A web app can fetch using RESTful data from the server. By using AJAX, this fetching is done asynchronously and in the background. AJAX makes a HTTP GET request using URL in this manner: http://example.com/resources/item17 and receives data of item 17 in JSON which can be displayed in view (web page). The following example of this use shows a weather example from wunderground.com. In this app, the user must make an account and receive a key in order to get Helsinki weather in JSON (http://api.wunderground.com/api/your-key/conditions/q/Helisinki.json). { “response”: { “version”: “0.1”, AngularJS Overview 32 AngularJS Best Practices Guide “termsofService”: “http:\/\/www.wunderground.com\/weather\/api\/d\/ terms.html”, “features”: { “conditions”: 1 } }. “current_observation”: { “image”: { “url”: “http:\/\/icons.wxug.com\/graphics\/wu2\/logo_130x80.png”, “title”: “Weather Underground”, “link”: “http:\/\/www.wunderground.com” }, “display_location”: { “full”: “Helsinki, Finland”, “city”: “Helsinki”, “state”: “ “, “state_name”: “Finland”, “country”: “FI’, “country_iso3166”: “FI”, “zip”: “00000”, “magic”: “1”, “wmo”: “02974”, “latitude”: “60.31999969”, “longitude”: “24.96999931”, “elevation”: “56.0000000” } AngularJS Overview 33 AngularJS Best Practices Guide This code example creates a Get Helsinki Weather button shown below the banner. After pressing the Get Helsinki Weather button, the current temperature and other details appears as shown in this example: FIGURE 11. The Get Helsinki Weather Button Example $resource Built on top of the $http service, $resource is a factory function that lets you interact with RESTful back-ends easily. $resource does not come bundled with the main Angular script and must be separately downloaded from the Angular-resource.min.js file. AngularJS Overview 34 AngularJS Best Practices Guide Your main app should declare dependency on the ngResource module in order to use $resource. $resource expects a classic RESTful backend such as: http:/./en.Wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services You can create the backend by whatever technology you require – even JavaScript (for example, Node.js). An example of the use of $resource in a script is shown in the following example: The result of this code is to create a text field and fetch button; when text is entered and the button clicked, relevant text appears as shown in the example above. $resource contains convenient methods for most operations including + + + + Get (GET) Save (POST) Query (GET isarray:true) Remove (DELETE) AngularJS Overview 35 AngularJS Best Practices Guide Calling any of these will invoke $https (an AJAX call) with the specified HTTP method (GET, POST, DELETE), destination, and parameters. You can use services with $resource in code as shown below: AngularJS Overview 36 AngularJS Best Practices Guide Or as in this example: AngularJS Animations AngularJS can also accommodate animations of various sorts, such as button clicks and mouse-overs, that result in changes to the screen. Such animations can prove useful for certain types of prompt-and-response screens. This entails the inclusion of an ngAnimate module as a possible dependency. ngAnimate modules enable you to hook animations for common directives such as ngRepeat, ngSwitch, and ngView. All of these directives are based on CSS classes, so if an HTML element has a class, you can animate it. AngularJS adds special classes to your html-elements. A simple example of animation and its result is shown in Figure 12. FIGURE 12. AngularJS Animation Example AngularJS Overview 37 AngularJS Best Practices Guide Animation Classes When adding a new name to the model, ng-repeat knows the item that is either added or deleted. CSS classes are added at runtime to the repeated element, such as when adding a new element, -
There are three assertions you must make while writing test script in QUnit:
+ Basic –
• -ok( Boolean [,message]);
+ If actual == expected
• -equal( actual, expected [, message]);
+ If actual ===expected
• -deepEqual( actual, expected [, message));
For more information on automating test using qunint, please refer to: http:////quintjs.com/
cookbook/#automating-unit-testing.
Using these assertions, testing AngularJS Service using QUnit can look like this example:
AngularJS Overview
41
AngularJS Best Practices Guide
var myApp = angular.module(‘myApp’), []);
//One service
myApp.service(“MyService”, function() {
this.add = function(a,b) {
return a + b;
};
});
/*TESTS*/
var injector = angular.injector([‘ng’, ‘myApp’]);
QUnit.test(‘MyService’, function() {
var MyService = injector.get(‘MyService’);
ok(2 == MyService.add(1,1));
});
Common Changes
This section provides information on some of the most common changes AngularJS can now
support.
Styling Changes
+ Using the same example found in the Troubleshooting section, we want to change the font
and color of the login heading text as shown in Figure 15.
FIGURE 15.
Changing the Font and Color of the Login Heading Text
AngularJS Overview
42
AngularJS Best Practices Guide
+ There is an added id=”tutorial-header-id” text element here to provide another way for
you to change the styling. There are now three easy ways to change the styling for this text.
The scss code below is added to the app.scss file.
#tutorial-header-id{
font-weight: 800;
}
.text--color{
color: blue;
}
user-id-header{
p{
font-size: 10px;
}
}
• First method: we target ID directly and change the boldness of the text
• Second method: there was already a class ‘.text-color’ that is associated with that text,
we can use that to make a change to the color. This is NOT preferable since this change
will affect other element that have this same class. (unless you want to do that)
• Third method: (personally preferred) we target the directive and target the tag within
that directive to make the change. This prevents the CSS styling from leaking out of the
intended target.
FIGURE 16.
Styling Method Examples
AngularJS Overview
43
AngularJS Best Practices Guide
As you can see, the CSS is applied in the screen shot from all three methods. But the only
issue you will have is when you apply by the predefined class. This affects all elements with
that class.
Text Changes
AngularJS now supports several types of text changes.
+ Using the same example in styling changes with the header text change. We want to create
a custom header text.
+ The following changes have been entered to userIdHeader.html:
The result of this change would be a page like the example in Figure 17.
FIGURE 17.
Public/Private Computer Radio Button Example
AngularJS Overview
44
AngularJS Best Practices Guide
Function Changes
To change the function of the submit button on the login page like this:
FIGURE 18.
Login Page Example
Currently, this example is triggering the form-post. You can change the function to generate an
alert message, such as in the following changes to the userIdButton.directive.js (see
“Troubleshooting Compiling and Deploying” on page 39 for guidance on locating directives).
'use strict';
angular.module('secureauth')
.directive('userIdButton', function (config, userIdView) {
var userIdButtonController = function () {
var vm = this;
AngularJS Overview
45
AngularJS Best Practices Guide
angular.extend(vm, {
submited: 'false',
userIdViewBtn: userIdView.getUserIdViewBtn()[0],
click: function (id) {
alert("test");
// var valid = angular.element('#aspnetForm').hasClass('ngvalid');
// if (valid && vm.submited === 'false') {
//
angular.element('#' + id).trigger('click');
//
vm.submited = 'true';
// }
},
dblclick: function () {
return false;
}
});
};
return {
restrict: 'EA',
controller: userIdButtonController,
controllerAs: 'UserIdButton',
templateUrl: config.theme + '/directives/UserIDView/userIdButton/userIdButton.html',
bindToController: true
};
});
Adding a New Element or Directive
Adding a new Element such as an tag or a new line of text can be done in multiple ways.
AngularJS Overview
46
AngularJS Best Practices Guide
Example: We want to add a link to the home login page right above the heading text.
Method One: Locate the directive in charge of printing the heading text and
know that this is the UserIDView. We can put the new link directly into the
directive html:
AngularJS Overview
47
AngularJS Best Practices Guide
Method Two: Locate the UserIDView.html in the views folder and insert the new link there. This
is NOT recommended because it strays from the structure of this framework.
Method Three (Recommended): Create a new directive under UserIDView.
Using the gulp tool, type: gulp theme:directive and the tool prompts for the location where
you would like to create the directive and the name of the directive. In this example, the name
should be camelCased.
AngularJS Overview
48
AngularJS Best Practices Guide
The new directive named ‘tutorialDirective.html’ is created under the UserIDView folder in
directives. In the tutorialDirective.html, insert the link code as shown below.
AngularJS Overview
49
AngularJS Best Practices Guide
To add the directive to the UserIDView, go to the view folder and locate useridview.html. Add
the new directive tag to it:
GitHub Tool
GitHub is a web-based Git repository hosting service. It offers all of the distributed version
control and source code management (SCM) functionality of Git as well as adding its own
features. Version control systems like GitHub keep the revisions straight and store the
modifications in a central repository. This allows developers to easily collaborate, as they can
download a new version of the software, make changes, and upload the newest revision. Every
developer can see these new changes, download them, and contribute.
Reproducing a Project
How do you clone and push from a personal repository back to a client branch? How do you
add a non-forked project? There is a method we recommend for doing this.
1. Clone your IDP branch, version, or whatever you want copied to your new repository in this
manner:
git clone git@sagithub-ent.secureauth.com:integration-development/idp.git
cd idp
git checkout
AngularJS Overview
50
AngularJS Best Practices Guide
2. Create a new repository in GitHub:
FIGURE 19.
GitHub Repository Example
AngularJS Overview
51
AngularJS Best Practices Guide
3. Follow the steps provided to push an existing repository.
In this case, you might have to change “origin” to “new” in this manner:
git remote add new …..
git push -u new
AngularJS Overview
52
AngularJS Best Practices Guide
4. Now you have a “new” repository to use (and fork or change) and can create branches for
each version.
FIGURE 20.
Branching and Forking Sample
GULP tools
GULP is one of the essential tools to create and compile code using AngularJS. There are
several commands that you will use repeatedly.
TABLE 5. GULP
Commands
Command
Uses / Reasons
gulp theme:view
Create a new view, such as for a new aspx form that requires a different
view to display it
gulp theme:directive
Create a new directive, such as when a new element is needed to
display new items/forms/text that shouldn’t be added to another
directive, or when new functionality is added to the aspx.
gulp theme:service
Create a new service, such as when a new view is created behind a new
aspx page.
gulp theme:boilerplate
Create a new theme from default themes.
gulp theme:build
Compile a theme and place it in the distribution folder (/dist)
AngularJS Overview
53
AngularJS Best Practices Guide
Route Object: Resolving Property
When routing to a view, the route object contains a “resolve” property that can accept a map
of promises and wait for them to resolve before preforming the route.
angular.module(‘moduleName’, [])
config(function($routeProvider)}
$routeProvider.when(“/”, {
templateUrl: ‘view.html’,
controller: ‘controller.js’,
resolve: //promise
})
})
});
View Controller
If every view managed by a controller can reflect the project structure by packing it together
and coming up with naming conventions, then views can comprise:
+ View-name
• View-name.html
• View-name.js
+ Another-view
• Another-view-name.html
• Another-view-name.js
The view-name.js is defined in the .controller(‘viewNameCtrl’… argument
Load Dependencies
Load dependencies occur as a reaction to an event. One approach is to load resources
depending on the user behavior in this manner:
+ Load only when a user starts to fill a form
+ Load by mouse position
+ Load when the server returns a response
Conclusions
AngularJS is a modular JavaScript SPA framework with lots of great features, but there is a
hard learning curve. The language is great for creating, reading, updating, and deleting apps,
but unsuitable for every type of app. However, it works extremely well with some JS libraries,
such as JQuery.
AngularJS Overview
54
AngularJS Best Practices Guide
Questions and Answers
How do you load scripts asynchronously?
RequireJS provides a clean way to load and manage dependencies as shown in this example:
define(function() {
//module code
})
require([‘module’], function(module) {
//use this module
})
How do you register components against a module after Bootstrap?
There are three essential points to remember when registering components.
+ Components register against the module in the config phase using providers. Register
controllers manually using $controllerProvider. An example of registering components is
shown in the following example:
angular.module(‘moduleName’, [])
.config(function($controllerProvider) {
$controllerProvider.register(‘Ctrl’, function() {
// controller code
})
});
+ All components can be registered with their matching provider methods:
// services can register with $provide
$provide.service()
$provide.factory(),
$provide.value(),
$provide.constant(),
// other components use specific providers
$controllerProvider.register()
$animateProvider.register()
$filterProvider.register()
$compileProvider.directive()
+ Hold a reference to this provider in order to use it later in code.
var app = angular.module(‘moduleName’, [])
Questions and Answers
55
AngularJS Best Practices Guide
.config(function($controllerProvider) {
app.loadController = $controllerProvider.register;
})
});
app.loadController(‘comeCtrl’, function($scope) {})
When does the actual loading occur?
Loading the program occurs when:
+ routing to a view - $routeProvider
+ loading content –
+ In response to event – like click or hover
Questions and Answers
56
AngularJS Best Practices Guide
Best Practices
Some of the best practices we like to recommend are:
+
+
+
+
+
+
Controllers and services should not reference the DOM
Controllers should have view behavior
Services should have reusable logic, independent of the view
Scope should be read-only in the templates
Be careful with simple examples
Your architectures should reflect the system not the frameworks you used in your system
MVC Flow
In general, MVC flow should follow the pattern shown in Figure 21.
FIGURE 21.
Recommended MVC Flow
Best Practices
57
AngularJS Best Practices Guide
Large Applications
Separating your code into multiple files is considered a best practice when building large
applications with AngularJS. For example:
angular.module(‘myApp.controllers’,[])
controller(‘MyCtrl1’, function() {
controller(‘myCtrl2’, function() {
});
Define each module as a dependency, as shown in this example:
angular.module(‘myApp,[‘ngRoute’,
‘myApp.filters’,
‘myApp.services’,
‘myApp.directives’,
‘myApp.controllers’,
‘ngRoute’,
‘ngResource’,
‘ui.bootstrap’,
])
Dependency injection (DI) is a software design pattern that deals with how components get
hold of their dependencies. The angular injector subsystem is in charge of creating
components, resolving their dependencies, and providing them to other components as
requested.
Components such as services, directives, filters, and animations are defined by an injectable
factory method or constructor function – injected with either “service” or “value” components.
Controllers are defined by a constructor function which can be injected with any of the
“service” and “value” components as dependencies, but they can also be provided with special
dependencies.
The run method accepts a function which can be injected with “provider” and “constant”
components as dependencies. You cannot inject “service” or “value” components into a
configuration.
Factory Methods
Factory functions use a unique way of defining a directive, service, or filter and are registered
with modules. The recommended way to do this is shown in the following example:
angular.module(‘myModule’, [])
.factory(‘serviceId’, [‘depService’, function(depService) {
//...
Best Practices
58
AngularJS Best Practices Guide
}])
.directive(‘directiveName’, [‘depService’, function(depService) {
//...
}])
.filter(‘filterName’, [‘depService’, function(depService) {
//...
}]);
Module Methods
Specify functions to run at configuration and runtime for a module by calling the config and
run methods. These functions are injectable with dependencies just like factory functions.
angular.module(‘myModule’, [])
.config([‘depProvider’, function(depProvider) {
//...
}])
.run([‘depProvider’, function(depProvider) {
//...
}]);
Controllers
Controllers are “classes” or “constructor functions” that are responsible for providing the
application behavior that supports the declarative markup in the template. The recommended
way to handle this is:
someModule.controller(‘MyController’, [‘$scope’, ‘dep1’, ‘dep2’, function($scope, dep1, dep2) {
...
$scope.aMethod = function() }
...
}
...
}]);
Unlike services, there can be many instances of the same type of controller in an application.
Additional dependencies are made available to controllers in this manner:
+
$scope – controllers are associated with an element in the DOM and so are provided with
access to the scope
+ Other components (like services) only have access to the $rootScope service
Best Practices
59
AngularJS Best Practices Guide
If a controller is instantiated as part of a route, then any values that are resolved as part of the
route are made available for injection into the controller.
Dependency Annotation
Angular invokes certain functions (like service factories and controllers) via the injector. You
need to annotate these functions so the injector knows what services to inject into the
function.
Three ways of annotating code with service information:
+ Using the inline array annotation (preferred)
+ Using the $inject property annotation
+ Implicitly from the function parameter names (has caveats)
The preferred approach, inline array annotation, involve the pass of an array whose elements
consist of a list of strings (the names of the dependencies) followed by the function itself.
When using this type of annotation, take care to keep the annotation array in sync with the
parameters in the function declaration.
someModule.controller(‘MyController’, [‘$scope’, ‘greeter’, function($scope, greeter) {
// ...
}]);
$Inject Property Annotation
To allow the minifiers to rename the function parameters and still be able to inject the right
services, the function needs to be annotated with the $inject property. The $inject property is
an array of service names to inject.
var MyController = function($scope, greeter) {
// ...
}
MyController.$inject = [‘$scope’, ‘greeter’];
someModule.controller(‘MyController’, MyController);
For more on this topic, refer to https://javascript-minifier.com/.
Implicit Annotation
If minifying will be done to the code, the service names will be renamed and will break the app.
The simplest way to get hold of the dependencies is to assume that the function parameter
names are the names of the dependencies.
Best Practices
60
AngularJS Best Practices Guide
someModule.controller(‘MyController’, function($scope, greeter) {
// ...
});
Strict Dependency Injection
The Ng-strict-di directive acts on the same elements as ng-app for strict DI mode in code
such as this:
I can add: {{ 1 + 2 }}.
‘willBreak’ Service
When the willBreak service is instantiated, Angular will generate an error because of strict
mode. This can prove useful when using ng-annotate to ensure that all of application
components have annotations.
angular.module(‘myApp’, [])
.factory(‘willBreak’, function($rootScope) {
// $rootScope is implicitly injected
})
.run([‘willBreak’, function($rootScope) {
// Angular will throw when this runs
}]);
Declarative Programming
Declarative programming creates user interfaces and connects software components. For
more on this features, refer to: https://www.youtube.com/watch?v=jfiMRue456w.
Best Practices
61
AngularJS Best Practices Guide
Large AngularJS Application
When writing a large program using AngularJS, almost all components can be brought into
play as shown in Figure 22.
FIGURE 22.
Large AngularJS Application Flowchart
This includes most of the objects and components previously defined and highlighted in this
guide.
Best Practices
62
AngularJS Best Practices Guide
References
For more information, please refer to the following topics:
+
+
+
+
+
+
http://docs.angularjs.org/guide
https://github.com/angular/angular.js/wiki
http://www.thinkster.io/pick/taQ0oMGII
http://www.youtube.com/angularjs
https://egghead.io/
http://joehooks.com
References
63
Source Exif Data:
This is the tutorial header text
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.5 Linearized : Yes Author : jbliss Create Date : 2017:06:20 10:59:35Z Modify Date : 2017:06:20 10:59:35Z XMP Toolkit : Adobe XMP Core 5.6-c015 84.159810, 2016/09/10-02:41:30 Creator Tool : FrameMaker 2015.0.4 Format : application/pdf Title : AngularJS Best Practices Guide.book Creator : jbliss Producer : Acrobat Distiller 15.0 (Windows) Document ID : uuid:1a5f5a0b-05b0-40ee-88ad-ce656aa3baf3 Instance ID : uuid:525d3f8a-5d26-4c4b-aba7-9243555b9dc4 Page Mode : UseOutlines Page Count : 68EXIF Metadata provided by EXIF.tools