William Liu

AngularJS


##Table of Contents


##Summary

AngularJS is a client side web framework in JavaScript. We break things down into View (UI), Controller (business logic), and ViewModel ($scope). We make things modular by using a module with a config file (angular.module().config([])). The config file goes to routes, which then splits into the above View and Controller.

####Why Angular

AngularJS is a JavaScript framework instead of a library (think lots of structure). Angular provides a higher level abstraction with a particular focus on CRUD (as opposed to making something like Games or GUI editors).

####Step through of an App

What happens when an Angular app loads?

On our browser, when we visit a web site, say we load a html page (aka template) that has some angular markup. What angular does in the background is it quickly parses the angular markup from the template using the compiler and first searches for an ng-app directive. That element and any child elements will then be handled with AngularJS. The compiler basically teaches the browser new behaviors for these elements. With the new features, the DOM is created and we call this a view.

So how is this different? In a standard multi-page web site and some single page applications, the server creates the HTML and joins the data on the server, then sends this finished response to the client browser. With Angular, the template and the data is sent to the browser and it gets assembled there using the compiler. Neat huh? The processing isn’t done mostly on the server anymore, but instead on the client’s browser.

####High Level Structure of an AngularJS App

So what’s the pieces of an Angular app? Angularjs follows the Model-View-Controller Pattern to structure a website; this structure decouples the code and separates concerns. A user interacts with the Controller, which then manipulates the Model, which then updates the View that is presented to the user. The pieces are:

####Comparisons to other JS Libraries and Frameworks


##Up and Running

Here’s a quick summary of how to get up and running with AngularJS.

##Module

Modules are a way to package relevant code under a single name. Each module creates its own controllers, services, directives. The first argument is the module name. You specify a second argument only if we’re looking up an existing module. If you want to create a new module, don’t add in a second argument. For example, below we call AngularJS to look up a module name (of store) and then we place our dependencies in the []. To create a module, we use the ng-app directive.

###Example: app.js

var app = angular.module('store', [ ]);

We then call this in our html under:

###Example: index.html

<html ng-app="store">
<body>
  <script type="text/javascript" src="app.js"></script>

##Data Binding

You can do one-way or two-way data binding. To get data back from an ng-model (e.g. <input type="text" ng-model="name">, you can use ng-bind or `` like the below example:

<h1>Hi <span ng-bind="name"></span></h1>
<h1>Hi </h1>

By default, we have two-way data binding. We may want one-way data binding in case we have a lot of elements on the screen and know only to update specific elements while leaving the rest alone (e.g. we know username won’t change). We use :: to one-way data binding:

<div ng-repeat="note in ctrl.notes">
    Without Bind Once: <div class="label" ng-bind="note.label"></div>
    With Bind Once: <div class="label" ng-bind="::note.label"></div>
</div>

##Controllers

Controllers are the business logic that goes in between the Model and the View. This means that controllers are the JavaScript functions that perform or trigger our UI-oriented work (non UI-oriented work is under Services. This could be fetching data from the server, deciding what to display to the user, user interactions like when someone clicks a button or text validation.

<html ng-app="notesApp">
<head><title>Notes App</title></head>
<body ng-controller="MainCtrl as ctrl">
   AngularJS.
  <br/>
   AngularJS

<script
  src="/Users/williamliu/GitHub/js-examples/angular/angular.min.js">
</script>
<script type="text/javascript">
  angular.module('notesApp', [])
    .controller('MainCtrl', [function() {
       this.helloMsg = 'Hello ';
       this.goodbyeMsg = 'Goodbye ';
  }]);
</script>
</body>
</html>

Main things to note are:

###Controller Example

<!-- File: chapter2/controller-click-message.html -->
<html ng-app="notesApp">
<head><title>Notes App</title></head>
<body ng-controller="MainCtrl as ctrl">
   AngularJS.

  <button ng-click="ctrl.changeMessage()">
    Change Message
  </button>
<script
  src="/Users/williamliu/GitHub/js-examples/angular/angular.min.js">
</script>
<script type="text/javascript">
  angular.module('notesApp', [])
    .controller('MainCtrl', [function() {
      var self = this;
      self.message= 'Hello ';
      self.changeMessage = function() {
        self.message = 'Goodbye';
      };
  }]);
</script>
</body>
</html>

##Directives

#Unit Testing and Test Framework

Karma for unit test runner and Jasmine for the test framework.

##Forms

To setup a form, we can do:

<form ng-submit="ctrl.submit()" name="myForm">
    <input type="text" ng-model="ctrl.user.username" required ng-minlength="4">
    <input type="submit" value="Submit" ng-disabled="myForm.$invalid">
</form>

There’s a lot going on, including:

###FormController

When you use forms and give them a name, AngularJS creates a FormController, which has the current state of the form. These states include:

You can use a few directives to help with form validation.

We can either display specific error messages and/or format with CSS (e.g. highlight field). For our CSS, we have a CSS class that goes with each:

###ngModel Options

With ng-model, we can add the ng-model-options directives that have the following options:

###ngForm

A regular HTML form does not allow nesting. The ngForm allows nesting (e.g. a subform inside a form).

##Services

AngularJS services are functions or objects that can hold behavior or state across the application. We only instantiate each Service once. Services can be implemented as factory, service, or provider; they are used in repeated behaviors, shared state, caches, factories, etc. For Services, you can use the $rootScope instead of $scope.

###Controllers versus Services

Controllers are the presentation logic while Services are the business logic. Controllers are directly linked to a view while Services are independent of views Controllers drives the UI while Services drives the application Controllers are one-off, specific while Services are reusable Controllers are responsible for decisions like what data to fetch, what data to show, how to handle user interactions, and styling and display of the UI Services are responsible for making server calls, common validation logic, application-level stores, and reusable business logic

##Dependency Injection

AngularJS services are singleton for the scope of the application (restrict instantiation of a class to only one object) AngularJS guarantees that the function we provide to the service declaration is only executed once lazily (the first time its called / needed); future dependents get that same instance.

###Safe style of Dependency Injection

Use this.

myModule.controller("MainCtrl", ["$log", function("$log") {}]);

You might see this style (though not recommended due to minification losing info about $log:

myModule.controller("MainCtrl", function($log) {});

###Order of Injection

Dependencies are injected based on the order in which they are listed. In the below, the $log service is injected into $l and the $window service is injected into $w.

myModule.controller("MainCtrl", ["$log", "$window", function($l, $w) {}]); 

###$

All AngularJS Services are prefixed with the $ sign, like $log, $http, $window. When you create your own service, do NOT use a $ sign.

##AngularJS Services

There’s three different ways to create and register services; these are by factory (functional programming style, return functions and objects), service() (Class/Object Oriented programming style), or by provider (usually used when we setup some configuration for the service before the application loads).

###Common AngularJS Services

###Creating a Service

If we’re creating a service using the factory method, we setup similar to a controller. We use the angular.module().factory function, as seen below.

angular.module('notesApp', [])
    .controller('MainCtrl', [function() {
        ...
        }])
    .controller('AnotherCtrl', ['ItemService', function(ItemService) {
        ...
        }])
    .factory('ItemService', [function() {
        var items = [
            {id: 1, label: 'Item 0'},
            {id: 2, label: 'Item 1'}
        ];
        return {
            list: function() {
                return items;
            },
            add: function(item) {
                items.push(item);
            }
        };
    }]);

##Server Communication Using the $http directive

$http allows you to do GET, POST requests. In our controller, we specify a dependency on $http, which we use like $http.get() followed by a .then(). This allows chaining of requests.

###Promises

Instead of callbacks, there’s promises. Promises solves the issue of nesting multiple callbacks (i.e. callback hell) and not having a common error handler.

###$q

The $q service allows you to trigger the error handler for the next promise in the chain. The $q service can create a deferred object with defer()

###Config file

When we do a $http method, we can pass in a config file. It might look like:

{
    model: string,  // e.g. GET or POST
    url: string,
    params: object,  // e.g. [{key1: 'value1', key2: 'value2'}] would be ?key1=value1&key2=value2
    data: string or object,
    headers: object,
    ...
}

This would be used like $http.get(url, config).

###$http defaults with $httpProvider.defaults

To setup a default config, we can use $httpProvider (in particular, $httpProvider.defaults) in the config section (angular.module().config([]))

###Interceptors

Interceptors handle request-level actions like logging and adding in some authorization heaers to the request (i.e. authentication checks). This is done with $httpProvider.

##Filters

AngularJS has filters that you can apply like ``. The json is a good way to debug. You can create custom filters with angular.module.filter()

##ngRoute

AngularJS routing is declarative, with all the routes in one configuration section where it specifies where the route is and what to do when the route is encoutered. In a single page application, we do not reload the entire page again. Instead, the shebang # denotes that the rest of the URL is loaded on the client side instead of the server side. For example, www.somepage.com/first/page/ to www.somepage.com/second/page loads the entire page while www.somepage.com/#/first/page to www.somepage.com/#/second/ doesn’t cause a whole page refresh.

###How routing is done

Routing is done using ng-view and define the routing in the config section using $routeProvider. We say $routeProvider.when(some_url, some_template_or_template_url) and .otherwise() as a default.

###Resolve

One of the route configuration options is resolve. Resolves are a way to execute finish asynchronous tasks before a particular route is loaded. This is a way to check if a user is logged in and has authorization and permissions. Resolves are a set of keys and functions. Each function can return a value or a promise.

###$routeParams

With $routeParams you can pass the context (i.e. additional information) across different routes.

##Directives

Directives can be classed into behavior modifiers (add or modify existing UI and HTML snippets like ng-show) and reusable components (where the directive renders whole new HTML using some type of rendering logic and some business logic). There’s two main directives for business logic built into AngularJS: ng-include and ng-switch.

###ng-include

ng-include is a directive that takes a path to an HTML file and replaces that with the HTML file. Note that if you inline the html file, put a set of ''. ng-include is good for extracting small snippets of HTML, but is limited in that naming variable needs to be consistent across all controllers and HTML files.

<div ng-include="mainCtrl.stockTemplate"></div>  // points to controller
<div ng-include="'views/stock.html'"></div>  // inline, notice the extra ''

###ng-switch

ng-switch is a directive that lets us add functionality to the UI for selectively displaying certain snippets of HTML. Basically, it’s a switch statement in HTML that shows different HTML depending on conditions (e.g. a bunch of tabs). This is used along with adding children elements with ng-switch-when and ng-switch-default directives.

##Custom Directives

What we want to do with custom directives is to make our intention declarative by specifying in the HTML what something is or tries to do while keeping it reusable. Creating a custom directive is similar to creating a Controller or Service; we define a directive definition object using angular.module.directive(). The limitation using this method is that we can only use this as <div stock-widget> and not <stock-widget>

// HTML
<div stock-widget></div>

// JavaScript
angular.module('stockMarketApp', [])
    .directive('stockWidget', [function() {
        return {
            // Directive definition goes here
            templateUrl: 'stock.html',
            restrict: 'AE',
            scope: {
                stockData: '=',
            },
            link: function($scope, $element, $attrs) {
                $scope.getChange = function(stock) {
                    return Math.ceil((stock.price - stock.previous) / stock.previous) * 100);
                };
            },
            replace: false
        };
}]);

Note on naming: AngularJS converts dashes to camelCase (e.g. stock-widget turns into stockWidget)

###Custom Directives Options: template / templateURL

###Custom Directives Options: link function option

With the link option, we pass in the scope of the element the directive is working on, the HTML DOM element the directive is operating on, and all the attributes on the elements as strings. This looks like link: function($scope, $element, $attrs) {}. Example code below:

link: function($scope, $element, $attrs) {
                $scope.getChange = function(stock) {
                    return Math.ceil((stock.price - stock.previous) / stock.previous) * 100);
                };
            }

The neat thing is that we pass in our scope. If we did <span class="stock-change" ng-bind="getChange(stock) + '%'"></span>, instead of binding to mainCtrl.getChange(stock), the stockWidget directive has its own scope.

##Custom Directives Options: Scope

The $scope (ViewModel) is the glue between the View and Controller. Each directive inherits its parent’s scope, which is passed to the link function. Its considered bad practice to modify the parent scope from the child. It ends up being an issue because adding variables/functions to the child modifies the parent, these variables might override existing variables with the same name, or if we rename properties.

The scope key can take one of three values:

##AngularJS Life Cycle

  1. The HTML page is loaded
    • The HTML page loads the AngularJS source code
    • The HTML page loads the application’s JavaScript code
  2. The HTML page finishes loading
  3. The document ready event is fired; AngularJS bootstraps and searches for any and all ng-app attribute in the HTML
  4. Within each ng-app, the compile step occurs:
    • The compile step goes through each line of HTML and looks for AngularJS directives
    • For each directive, it executes the necessary code defined by the directive’s definition. This might load or create new HTML
    • At the end of the compile step, a link function is generated for each directive that has a handle on all the elements and attributes that need to be controlled by AngularJS
  5. AngularJS takes the link function and combines it with the scope. The scope has the variables and contents that need to be displayed in the UI. This generates the live view that the user sees and interacts with.
    • Each controller and subcontroller is instantiated with its own scope that will be used to display data in the UI
    • AngularJS adds watchers and listeners for all the directives and bindings to ensure it knows which fields it needs to track and which data field to bind
  6. We have a live, interactive view with the content filled in for the user

###The Digest Cycle (Updates to UI)

AngularJS updates the UI in response to one of the following events: * The user makes a modification (types in, check checkbox, click button) * A server request is made and its response comes back * A $timeout or $interval is used to execute something asynchronously

##Third Party Libraries

###Bower

Manage, update, version your third party packages using Bower, a package management tool. Install with npm install bower, then list your dependencies usually in a file bower.json. To install, do bower install or bower update. You won’t need to put third party libraries into your repository and others can see what libraries and versions you’re using. When you install with bower, you can save additional information using $bower install --save option.

###Grunt

You can install Grunt CLI, the Command-line interface for Grunt. This will allow you to do the following commands:

###Yeoman

Yeoman is a workflow management tool.

##Questions

[check] * How to structure? Use yeoman to get setup; install with ‘grunt’,

Peter created ng-django, passed in context; https://github.com/Tivix/django-base-project/tree/angularjs-components/django_base_project/django_base_project/apps/ngDjango Use Angular tells element how to behave, Django serves up the template

Example Projects with AngularJS:

https://www.madewithangular.com/#/