Introduction

Angular great for creating dynamic website:
- helps organise JavaScript
- helps create responsive (fast) websites
- plays well with jQuery
- easy to test

Responsive:
- traditional web app will reload entire page again
- with Angular, each link click will only update information needed to update the page

Modern API-driven application:
- data source -> API
- API -> developers, mobile app, browser app

AngularJS can be defined as a client-side JavaScript framework for adding interactivity to HTML
- how do we tell our HTML when to trigger our JavaScript?

Client-side Templates

In AngularJS, the template and data get shipped to the browser to be assembled there.  The server role is only to serve as static resources for the templates and to properly serve the data required by those templates.
- no classes or IDs in the HTML to attach templates
- don't register event listeners or write callbacks

Model View Controller (MVC)

- view is the DocumentObjectModel (DOM)
- controllers are JavaScript classes
- model data is stored in object properties

Data Binding

Data binding: declaring which parts of the UI map to which JavaScript properties to sync automatically.  Allows the UI to dynamically update without registering change listeners on the input field.

Dependency Injection

Instead of creating dependencies, the classes just ask for what they need.  This follows a design principle called the 'Law of Demeter', aka the principle of least knowledge.  Since a controllers job is to, for example, set up the initial state for a model, the principle says it shouldn't worry about anything else, such as how the object passed to it got created.

Directives

In Angular, templates are written in HTML.  At the core the of the framework, is DOM transformation engine that extends HTML's syntax.  Angular comes with included directives, or can write own directives.

Directives are a marker on HTML tag that tells Angular to run or reference some JS code

<html ng-app="appName">

Anatomy of an AngularJS Application

Invoking Angular

An Angular app must:
- load angular.js library
- tell angular which part of the DOM it should manage with the ng-app directive.

ng-app directive will tell Angular which part of the page to manage. All-Angular application can place ng-app directive as part of the HTML tag.  If using Angular in conjunction with another technology that expects to manage the DOM, can place ng-app directive on a div.

MVC

A Angular app will always have some flavour of:
- a Model for containing data that represents the current state of the application (stored in JS object properties)
- Views that display the data (the DOM in HTML)
- Controllers that manage the relationship between model and views (which are JS classes)

Model is inserted into DOM using {{someObject}} notation (called double-curly syntax interpolation).

Controllers are JavaScript classes that:
- help us get data onto the page
OR
- where we define our apps behaviour by defining functions and values

The scope of a controller exists only inside DOM element / div.  It cannot access outside its div.
- alias = alias used inside expressions

<div ng-controller="ControllerName as Alias">

Controllers are classes or types which tell Angular which objects or primitives make you your model, by assigning them to the $scope object passed into your controller:

function TextController ($scope) {
  $scope.someText = someText;
}

However, this does create TextController in the global scope.  The best way to define a controller is as part of a module, which provides a namespace for related parts of the application.

Modules:
- where we write pieces of our Angular application
- keep code encapsulated: makes code more maintainable, testable and readable
- where we define dependences of app (for example, this module depends on these two modules)

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

Scope

$scope sits as one of the main Objects that power the two way data-binding cycles to maintain application state.  The $scope Object sits in JS to access data and values, it also represents those values out in the DOM once Angula renders our app.  $scope is a glorified ViewModel.

The $rootScope is the very top level $scope from which all further scopes are created.  Once Angular starts rendering the application, it create a $rootScope Object and all further bindings and logic in the application create new $scope Objects, which become children of the $rootScope.

The $scope object passed to controllers is the mechanism used to expose model data to views.  May have other application data, but Angular only considers it part of the model when it can reach these properties through a scope.  Can think of scopes as a context that you used to make changes to the model observable.

Can indirectly set up scopes through an expression:

<div ng-controller='CountController'>
  <button ng-click='count=3'>Set count to three</button>
</div>

UI Responsibilities with Controllers

Controllers have 3 responsibilities:
- set up initial state in application's model
- expose model and functions to the view (UI template) through $scope
- watch other parts of the model for changes and take action

An Angular controller allows us to interact with a View and Model.  The controller is the place where presentational logic can take place to keep the UI bindings in sync with the Model.  Its the meetings place between business logic and presentation logic.

Create one controller per functional area in the view. I.e. MenuController, BreadcrumbController and so on.

For complex UI, can keep code simple and maintainable be created nested controllers that share model and functions through an inheritance tree.

A controllers accepts two arguments: the first is the Controllers name, and the second a callback function. To avoid the function callback from looking like a callback and to save indenting a lot, can place the callback function outside Angular's syntax and pass any functions into it:

function MainCtrl () {
  // Controller functions in here
}

angular
  .controller('MainCtrl', MainCtrl);

ControllerAs syntax

The Controller talks to a Service, and passes the data in either the same or a different format across to our View, using the $scope Object.

Using 'controllerAs ' syntax, Controller becomes instantiated as an instance under a variable (much like could using the new keyword against a variable to create a new Object).

Using controllerAs:
- replace $scope reference for data bound inside the Controller for this.
this.items = [];
- use 'Ctrl as main' to create a main variable, and items becomes main.items.

Templates and Data Binding

Templates in Angular are HTML documents loaded from the server or defined in a script tag, just like any other static resource.  The UI is defined in the template, using standard HTML plus Angular directives where need UI components.  In the web browser, Angular expands these templates into a full application, merging template with data.

Startup workflow:
- user request first page of the app
- browser makes a HTTP connection to the server and loads the index.html page containing the template
- Angular loads into the page, waits for it to be fully loaded.  Then looks for ng-app to define its template boundaries.
- Angular traverses the template and looks for directives and bindings.  This results in listeners and DOM manipulation, as well as fetching initial data from the server.  End result of this work is app is bootstrapped, and template is converted into view as a DOM.
- user connects to server to load additional data to show the user as needed

Templates separate to data, therefore the templates are cacheable (better performance).

Expressions

Expressions in templates can do simple math (+, -, /, *, %), make comparisons (==, !=, >, <, >=, <=), perform boolean logic (&&, ||, !) and bitwise operations (\^, &, |).
You can call functions you expose on $scope in your controller and you can reference arrays and object notation ([ ], { }, .).

Should keep application logic out of template though.

Angular expressions are JS-like snippets of code the can be used amongst templates to conditionally change the DOM.  These expressions like inside handlebar template bindings {{ value }}.

ng-click

With ng-click don't need to manually bind event listeners to multiple elements, Angular will evaluate the expression/s inside the ng-click for us and bind the event listeners.

Displaying Text

ng-bind directive will display and update text anywhere on the UI.
<p>{{greeting}}<p> (may render initially on first page, so use other form on index.html)
OR
<p ng-bind="greeting"></p>

Form inputs

Can use ng-model attribute to bind element to model properties.

<form ng-controller="SomeController">
  <input type="checkbox" ng-model="youCheckedIt">
</form>

- when user checks the box, a property called youCheckedIt on the SomeController's $scope will become true.  Unchecking the box makes youCheckedIt false.

ng-init directive allows us to evaluate an expression in the current scope.  Although good practice to create a controller instead of ng-init to initialise a model.

For input elements, can use the ng-change attribute to specify a controller method that should be called whenever the user changes the input's value.

To update a field no matter how it gets updated (say from the server), use $watch().  You call $watch() - a callback that gets invoked whenever the expression changes.

ng-submit specifies a function to call when the form submits.

Angular provides event-handling directives resembling browser's native attributes. ng-click (onclick), ng-dbclick (ondbclick) and so on.

Validations for forms:
- need to turn off default HTML form validations: add 'no validate'
- set which fields required with 'required' in the field element

Prior to input, the source has the class ng-pristine (untouched) and ng-invalid.  As typing, class is updated to ng-dirty and ng-invalid. After a valid email, class changes to ng-dirty ng-valid.
- can therefore update the css to update the design to suit.

Angular has buit-in validations for common input types:
<input type="email" name="email">
<input type="url" name="homepage">
<input type="number" name="quantity"> // can also define with min and max: min=1 max=10

Lists, Tables, and Other Repeated Elements

Use ng-repeat to create lists of things: it creates a copy of a set of elements once for every item in a collection.

ng-repeat directive: iterate through items in an array
<div ng-repeat="item in controllerAlias.array"> // For example, <div ng-repeat="product in store.products">

ng-repeat directive gives reference to the index of the current element via $index, and booleans that tell you if you're $first, $middle, or $last.

Hiding and Showing

ng-hide and ng-show directives show and hide elements (for menus, context-sensitive tools etc).  Provide inverse functionality for showing and hiding based on the expression passed to them. I.e., ng-show will show when its expression is true.

ng-show directive: specify an expression that will show only if value of expression is true
<button ng-show="controllerAlias.product.expression"> Add to Cart </button>

ng-hide directive: hide if expression evaluates to true
<div ng-hide="controllerAlias.product.expression"> // For example, hide if soldOut: true

CSS Classes and Styles

Can dynamically set classes and style in application by data binding them and using {{ }} interpolation notation.

CSS:

.menu-disabled-true {
  color: gray:
}

HTML:

<div ng-controller='DeathrayMenuController'>
  <ul>
    <li class='menu-disabled-{{isDisabled}}' ng-click='stun()'>Stun</li>
  <ul>
</div>

JS:

function DeathrayMenuController ($scope) {
  $scope.isDisabled = false;
  $scope.stun = function () {
    // do whatever
    $scope.isDisabled = 'true';
  };
}

As initially false, the result will be menu-disabled-false.  This technique works well with combining inline styles with interpolation: style='{{some expression}}'.

Problems with this can be difficult to read JavaScript and CSS to create template.  Because of this have ng-class and ng-style.

ng-class and ng-style directives can set the class for the element.  Pass in an object, with the name of the class to set, and an expression to evaluate.  If true, append the class to the element, otherwise do not.
<li ng-class ="{ active: tab === 2 }">

Result of evaluating the passed in expression can be:
- a string representing space-delimited class names
- an array of class names
- a map of class names to boolean values

src and href Attributes

- if use an Angular expression inside a src, will cause an error because the browser tries to load the image before the expression evaluates.  Need to use ng-src and ng-href.
<img ng-src"{{product.images[0].full}"/>
<a ng-href="/shop/category={{numberOfBallons}}">some text</a>

Observing Model Changes with $watch

$watch notifies you when parts of the model change:
$watch(watchFn, watchAction, deepWatch)
watchFn: a string with an Angular expression or a function that returns the current value of the model to watch
watchAction: a function or expression to be called when watchFn changes.  If a function, it receives the new and old values of watchFn as a reference to the scope: function(newValue, oldValue, scope).
deepWatch: if set to to true, the optional parameter tells Angular to examine each property within the watched object for changes.

There are performance considerations with watch().

Organising Dependencies with Modules (provider, factory and service)

By convention all custom Services should follow Pascal case (for example 'MyService').

Modules provide a way to group dependencies for a functional area within the application, and a mechanism to resolve dependencies (dependency injection).  Generally, dependencies are called services because they provide services to the application.

Need to register dependencies as services to inject into other controllers.

Services are what we create to hold application's Model data and business logic (for example talking to server over HTTP).

Services are single-instance objects that carry out the tasks necessary to support application's functionality.  Angular comes with Services built-in which can use to provide a controller additional functionality.  For example, fetching data from a json api with $http service, logging messages to console with $log, or filtering an array with $filter, $route for switching views based on location (URL) changes.

Should create services to do all the tasks unique to your application.  Services can be shared across any controllers that need them. (Angular's bundled services start with $).  It's best to organise the application modules based on functionality.  For example, app.js would include top-level module / functionality attached via ng-app, all product related functionality would be placed in products.js and so on.

There are three functions for creating generic services, with different levels of complexity and ability:

Service Method

Angular assumes that the function definition passed in as part of the array of dependencies is actually a JavaScript type/class.  So instead of just invoking the function and storing its return value, Angular will call new on the function to create an instance of the type/class.  Angular gives a service method for creating a new Object (to talk to a backend or provide utilities to handle business logic).  A service is a constructor Object that gets called with the new keyword, which means we use the this keyword to bind our logic to the Service.  The service creates a singleton Object created by a service factor.

service (name, constructor () ) // a non-configurable service with simple creation logic.  Like the constructor option with provider, Angular calls it to create the service instance.

A Service means we can't run any code before it as all methods are the Object instantiated.

User service method:
- if follow a Class/OO style of programming, where define classes and types instead of functions and objects

Factory Method

Factory methods return an Object or a Function, which means we can make usage of closures as well as returning a host Object to find methods to.

All Factories become a Service, so we should refer to them as a Service rather than the pattern they are named after.

factory (name, $get Function() ) // a non-configurable service with complex creation logic. You specify a function that returns the service instance when called. I.e. provider (name, { $get: $getFunction() } ).

Use factory method:
- if follow functional style of programming
- prefer to return functions and objects

Provider Method

provider (name, Object OR constructor() ) // a configurable service with complex creation logic.  If you pass an Object, it should have a function named $get that returns and instance of the service.  Other, Angular assumes you've passed a constructor that create the instance when called.

Use provider method:
- to set up configuration for service before application loads
- with provider can have functions that can be called to set up how service works based on the language, environment or other things applicable to our service.

How Many Modules?

As services themselves have dependencies, the Module API lets you define dependencies for dependencies.
var appMod = angular.module('app', ['someDependency', 'someOtherone']);

Filters

{{ data | filter:options }}
- the pipe "|" says: take the result of the first expression and send the output into the second expression

For example:
{{ data | currency }} // {product.price | currency }}
{{ data | date: 'MM/dd/yyyy @ h:mma'}}
{{ data | uppercase }}
{{ data | lowercase }}
{{ data | limitTo:8 }} // can limit characters, or the number of items in an array

<li ng-repeat="product in store.products | orderBy: '-price'"> // allows us to sort by, descending with a -, ascending without

Filters can be chained : {{12.9 | currency | number: 0 }} // number sets the number of decimal points

Title case custom filter example: pg. 38.

Changing Views with Routes and $location

$route service can manage sub-page views of SPA.  Routes specify for a given URL what template to display, and which controller to instantiate.

Routes are created by calling functions on the $routeProvider service, as a configuration block.

Router is not packaged by default.  Instead, we need to include 'ngRoute' as a dependency (and include JS file).  With ngRoute available, can confifure the routes by injecting $routeProvider and setting it up inside the Angular .config() method.

Talking to Servers

Can fetch json data with $http service by using $http service as a function with an options object:
$http({ method: 'GET', url: '/products.json' });
OR
By using shortcut method:
$http.get('/products.json', { apiKey: 'myApiKey' }); // any additional query parameters can be specified in the JavaScript object.

Both return a Promise object with .success() and .error() (ala jQuery).  $http supports HTTP, JSONP and CORS.

If use $http to fetch JSON, result will be automatically decoded into JavaScript objects and arrays

Controller needs to tell Angular which services it needs using funky array syntax:

// the name of the services controller needs become arguments in the controller function
// This is called dependency injection: Injector passes in services as arguments to the Controller
app.controller('SomeController', [ '$http', '$log', function($http, $log) {
  var store = this; // use store.products instead of this.products
  // Initialise products to an empty array, that way when the page loads it will render before      
  // our data returns from its get request
  store.products = [ ];
  $http.get('/products.json').success(function(data) {
    // Fetch the contents of /products.json
    // $http returns a callback promise, so success() method gets the data
    // need to do something with data: really need to set it equal to this.products, but can't 
    // write this.products, because inside callback 'this' is the service $http
    // instead use the variable store, set equal to this.
    store.products = data;
  });
} ]);

Changing the DOM with Custom Directives

It's time to break into custom directives when you want to deal with browser events or modify the DOM in a way that isn't already supported by built-in directives.

If using a template, its preferable to use a Custom Directive because a directive allows you to write HTML that expresses the behaviour of your application.

Template-expanding Directives:
- define a custom tag or attribute that is expanded or replaced
- can include Controller logic, if needed

Pull out code into new file, then include the template file with ng-include and single and double quotes (because ng-include is expecting a variable with the name of the file to include.
<h3 ng-include="'template-file.html'"</h3>

Other uses:
- expressing complex UI
- calling events and registering event handlers
- reusing common components

Various types of Custom Directive:
- use Element Directives for UI widgets and Attribute Directives for mixin behaviours like a tooltip.

Element Directive (E):
<product-title></product-title> // notice not using self-closing tag because some browsers don't like self-closing tags

Attribute Directive (A):
<h3 product-title></h3>

Angular allows you to write expressive HTML through Custom Directives so people can read HTML and understand behaviour and intent of the web application.

Directives are defined through the module object's API by calling its directive() function, where directiveFunction is a factory function that defines directive's features.

var appModule = angular.module('appModule', [ ] );
appModule.directive('directive name', directiveFunction);

Validating User Input

Angular lets us declare valid states for inputs with the form and allow submission only when the entire set of elements is valid.  HTML5 required for input.

$valid access the validation state of the input inside the controller.

Developing in AngularJS

Example Application

Communicating with Servers

Communicating using $http

Traditional way of making request to the server from AJAX application (using XMLHttpRequests) involves getting a handle on the XMLHttpRequest object, making the request, reading the response, checking the error codes, and processing the server response.

AngularJS XHR API follows Promise interface. Use $http service (offers GET, HEAD, POST, PUT, DELETE, JSONP).

$http can get(), post(), put() delete() as well as any other HTTP method using a config object:
$http.post('/path/to/resource.json', { param: 'value' });
$http({ method: 'OPTION', url: '/path/to/resource.json' });

$http({
  method: string,
  url: string,
  params: object,
  data: string or object,
  headers: object,
  transformRequest: function transform(data, headersGetter) or an array of functions,
  transformResponse: function transform(data, headersGetter) or an array of functions,
  cache: boolean or Cache object,
  timeout: number,
  withCredentials: boolean
});

Working with RESTful resources

$http service provides low-level implementation to make XHR requests.  If want to create JS objects that understand / represent model, edit properties of the object, save or update etc need to use $resource service with ngResource.
- has additional methods (get ,save, query, remove, and delete)
- resource allows you to work with the returned object as if they were persisted data models, make changes, and ask them to be persisted.

ngResource is a separate optional model.  To use it, need angular-resource.js sourced, include ngResource in module dependency declaration, and inject $resource where needed.

The $q and the Promise

The Promise proposal is how Angular structures its API:
- async requests return a promise instead of a return value
- the Promise has a then function, which takes two arguments, a function to handle the 'resolved' or 'success' event and a function to handle the 'rejected' or 'failure' event.  One of these callbacks will be called.

Need to set up a Response Interception factory (service).

Directives

Directives definition options:
restrict: Declare how directive can be used in a template as an element, attribute, class, comment, or any combination.
priority: Set the order of execution in the template relative to other directives on the element.
template: Specify an inline template as a string. Not used if you're specifying your template as a URL.
templateUrl: Specify the template to be loaded by URL. This is not used if you've specified an inline template as a string.
replace: If true, replace the current element. If false or unspecified, append this directive to the current element.
transclude: Lets you move the original children of a directive to a location inside the new template.
scope: Create a new scope for this directive rather than inheriting the parent scope.
controller: Create a controller which publishes an API for communicating across directives.
require: Require that another directive be present for this directive to function correctly.
link: Programmatically modify resulting DOM element instances, add event listeners, and set up data binding.
compile: Programmatically modify the DOM template for features across copies of a directive, as when used in ng-repeat. Your compile function can also return link functions to modify the resulting element instances.

Other Concerns

$location

$location is a wrapper around the window.location present in any browser.

Pg 138: when and when not to call $apply.

The 'Main Method' ala python is not present in Angular.  Instead app is bootstrapped by ng-app in HTML.

Cheatsheet and Recipes

jQuery data picker
File upload
Pagination
Server
Socket.io