Beginning AngularJS

Preview:

Citation preview

Beginning AngularJS16 August 2014, Torrance California Troy Miles

Troy Miles

Over 30 years of programming experience

Blog: http://therockncoder.blogspot.com/

Twitter: @therockncoder

Email: rockncoder@gmail.com

GitHub: https://github.com/Rockncoder

AgendaModernWeb Application

Introduction to AngularJS

Lab - Two Way Data Binding

AngularJS Core Concepts

Todo app

Providers / Services / Factories

Agenda (continue)

Contacts app

Filters

Lab - Using Filters

Directives

Lab - jQuery UI Widget

Wrap-up

What We Aren’t CoveringBootstrap

Unit Testing

End to End Testing

Custom Directives

Nested Views + ui-router

HTML5 History API

Modern Web Applications

Lab - Hello AngularJS

In the class project folder (ng-contacts)

In the exercises directory

Launch the hello.html web page

You should see a greeting displayed

Lab Solution

Browser expect web applications to be delivered via a web server

While most browser will allow a web page to run from a file, most won’t allow it to access other files

If your machine is setup correctly, you will see a greeting

Modern Web Applications

A Quick History of the Web

Single Page Applications Explained

Early Web App Problems

Contrasting AngularJS & jQuery

Other JavaScript MVC Frameworks

A Quick History of the Web1996 - Microsoft introduces the iframe in IE

1999 -Microsoft introduces the XMLHTTP ActiveX control

2004 - GMail & Kayak, two heavily ajax’ed apps

2005 - Jesse James Garrett’s article coins the phrase AJAX

2006 - jQuery introduced

Text

Single Page Applications Explained

Early Web App Problems

They were difficult to build, maintain, enhance, and test

They broke SEO, history, and bookmarks

They were all different

They lacked structure

Lab - jQuery Data BindingFrom the exercise folder open the binding.html file

Write JavaScript to transfer the text contents of the input tag with the id of firstName, to the span with the id of showName

The code should be interactive and update as the user types

Write you code in the empty script tag near the end of the page

jQuery is already included on the page

jQuery Example<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>Binding</title> <script src="../lib/jquery-1.10.2.min.js"></script></head><body> <label for="firstName">Enter Your Name:</label> <input type="text" id="firstName"/> <h2>Display Your Name Below</h2> <label for="showName">Show Your Name:</label> <span id="showName"></span> <script> $( document ).ready( function(){ $('#firstName').on("keyup", function(){ $('#showName').text(this.value); }); }); </script></body></html>

What’s Wrong with jQuery

jQuery is a very popular library

It is used on 50% of all web sites

It is difficult code to test

It leads to creation of spaghetti code

How about this…$(document).ready(function () { $('#Slp-select-slim-content .mod-content').height($('#Slp-browse-categories .mod-content').height()); $('#Browse-category .browse-category li').click(function () { window.location = $(this).find('a').attr('href'); }); $('#Slp-browse-cat-link, #Slp-browse-make-link, #Slp-browse-oem-link, #Slp-browse-cpo-link').click(function () { var $this = $(this); if ($this.hasClass('disabled')) return false; $('#Slp-browse-cat-link, #Slp-browse-make-link, #Slp-browse-oem-link, #Slp-browse-cpo-link').removeClass('disabled'); $this.addClass('disabled'); $('#Browse-category, #Browse-make, #Browse-oem, #Browse-cpo').hide(); switch (this.id) { case "Slp-browse-cat-link": $('#Browse-category').show(); break; case "Slp-browse-make-link": $('#Browse-make').show(); break; case "Slp-browse-oem-link": $('#Browse-oem').show(); break; case "Slp-browse-cpo-link": $('#Browse-cpo').show(); break; } $('#Slp-select-slim-content .mod-content').height($('#Slp-browse-categories .mod-content').height()); return false; });

AngularJS Example<!DOCTYPE html><html ng-app><head lang="en"> <meta charset="UTF-8"> <title>NG-Binding</title> <script src="../lib/angular.min.js"></script></head><body> <label>Enter Your Name:</label> <input type="text" ng-model="firstName"/> <h2>Display Your Name Below</h2> <label>Show Your Name:</label> <span>{{firstName}}</span> <script> </script></body></html>

AngularJS vs jQuery

AngularJS jQueryextensible yes yes

IoC yes nodefault behavior yes no

testable yes no2way binding yes nominified size 106 kb 84 kb*

Other JavaScript MVC Frameworks

Backbone.js

Knockout

EmberJS

Other frameworks & ToDoMVC

Backbone.jsCreated by Jeremy Ashkenas in 2010

19 kb production version (minimized, not gzipped)

One dependency - Underscore.js, optional jQuery

Three core concepts: models, collections, & views

Uses lots of custom events

KnockoutCreated by Steve Sanderson in 2010

47 kb production version (minimized, not gzipped)

Uses MVVM pattern

Two way data-binding

No dependencies

Supports all mainstream browsers

EmberCreated by Yehuda Katz and Tom Dale in 2011

Convention over configuration

Ember Data, a separate package, handles RESTful data

Handlebars.js, a separate package, handles templates

337 kb production version (minimized, not gzipped)

Other frameworksDojo

YUI

Agility.js

Knockback.js

CanJS

Maria

Polymer

React

cujoJS

Montage

Sammy.js

Stapes

Batman.js

http://todomvc.com/

Beginning AngularJS

AngularJSCreated by Miško Hevery and Adam Abrons in 2009

JavaScript MVC

106 kb production version (minimized, not gzipped)

Declarative programming for UI

Imperative programming for business logic

AngularJS Key Features

Two Way Data-binding

Model View Controller

Dependency Injection

Deep Linking

HTML Templates

Directives

Testability

Two Way Data-binding

In AngularJS, binding is built into the framework

Replaces text content of HTML element with the value of the expression

{{ expression }}

<ANY ng-bind=“expression”>…</ANY>

<ANY class=“ng-bind: expression;”>…</ANY>

Model View Controller

Uses MVC or MVVM or MV* depends on who you ask

The goal is clear separation of concerns

The model is only concerned with data

The view presents the data to the user

The controller applies the business logic

Dependency InjectionA software design pattern that implements inversion of control and allows a program design to follow the dependency inversion principle

Allows a dependency to be passed to an object

Allows code to clearly state dependencies

Leads to code which is easier to debug and test

Makes it possible to minimize apps without breaking them

Dependency InjectionThe DI pattern in AngularJS looks funky due to JavaScript’s shortcomings

The pattern is name of module, dot, name of provider, name of object, an array with the list of dependencies in strings and a function as the last item in the array

tempApp.controller('CurrentCtrl', ['$scope', function ($scope) { $scope.temp = 17; }]);

Deep Linking

One feature that web sites have over desktop apps are bookmarks

Deep linking allows AngularJS to restore state based on a URL

Application can use hyperlinks to navigate users around

HTML Templates

There are a lot of templating libraries

AngularJS instead uses HTML for its templates

AngularJS templates can pass HTML validators

Designers will feel at home

Easy to learn

Directives

Possibly the best thing in AngularJS

Directives extend the capabilities of HTML

Merge the declarative nature of HTML to the imperative nature of JavaScript

Testability

AngularJS was engineered with testing in mind

It supports both unit and integration tests

For unit tests it works well with Jasmine

For end to end tests it supports Karma

Strict Mode

Strict mode allows you to opt in to a more restrictive version of JavaScript

Things usually permitted in JS become errors

Can be applied to an entire script or individual functions

Strict mode is a JavaScript best practice

Invoking Strict Mode!

Before any other statements place the following statement

"use strict"; or

'use strict’;

Works on both the script and function level

Be careful of mixing strict and non-strict mode files

$scopeAn object which refers to the application model

The glue between the controller and the view

The execution context for expressions

Provides APIs

$watch - observes model

$apply - propagates model changes to AngularJS

Name ManglingThere are basic incompatibilities between names used in HTML and those in JavaScript

HTML permits dashes and colons, JS does not

To convert to JavaScript

delete any initial x-, data-

First letters after are capitalized

delete dashes, underscores, and colons

Name Mangling

So all of the following attributes equal timePicker:

data-time-picker

x:time-picker

time_picker

AngularJS Directives

ng-app

ng-controller

ng-model

ng-bind

ng-repeat

ng-bind vs ng-modelng-bind is one way data binding, aka output

ng-bind renders a property on scope

ng-bind has a shortcut {{}}

ng-bind is preferred over shortcut

ng-model is for two-way data binding

ng-model is intended for form elements

<input ng-model='userName' />

Lab - Greet-o-matic

Open the greet-o-magic.html file

Make the page functional

The user should be able to enter their name in either input tag and have it reflect in the other and in the span tag

You shouldn’t need to write any JavaScript

Two Way Data-binding<!DOCTYPE html><html ng-app><head lang="en"> <meta charset="UTF-8"> <title>Greet-o-matic</title> <link rel="stylesheet" href="../css/bootstrap.css"/> <script type="text/javascript" src="../libs/angular.js"></script></head><body><div class="container" > <h1>Greet-o-matic</h1> <div class="col-lg-6"> <input type="text" ng-model="userName" placeholder="Enter name here"/> </div> <div class="col-lg-6"> <input type="text" ng-model="userName" placeholder="or over here"/> </div> <hr/> <p>Hello <span>{{userName}}</span>,<br/>Have a nice day!</p></div></body></html>

Where’s the main function?

In many languages there is a main function which is where execution begins

The close thing to it in AngularJS is angular.module()

The order of execution is not guaranteed or specified

Code Along - Initial Values

What if we wanted to have a name in the input tag?

To support that we need some JavaScript

First we must create a app module

Next we must create a controller

The controller exists both declaratively and imperatively

Code Along - Todo App

A Todo app is the hello world app of JavaScript MVC frameworks

It shows how to create an app which creates, reads, updates, and deletes data (CRUD)

Let’s build one together

Open the files todo.html and todo.js

Code Along - Todo App Steps

create shell page with angular link

create script tag for JS

add ng-app with module name ‘ToDo’

create angular module

create todo controller

create todos array

create add method

create delete method

create complete method

Code Along - Todo App Steps

add markup

add functionality to methods

clear text box after added

Providers

What are providers?

Types of providers

Services

Factories

Providers

What are providers?

Objects that are instantiated and wired together automatically by the injector service

The injector creates two kinds of objects:

services - defined by the developer

specialized objects - Angular framework pieces, controllers, directives, filters, or animations

Types of providersConstants

Value

Decorator

Provider

Service

Factory

Services

Substitutable objects that are wired together using DI

Used to organize and share code across app

Only instantiated when an app component depends on it

Singletons

Built-in services always start with “$”

Factories

Introduction to shared components

Dependency injection deep dive

Building custom factories & services

Persisting data to a Web API service

FirebaseA powerful AP to store and sync data in realtime

Offer free developer accounts

Both backend data and hosting

No real arrays (limitation due to contention problem)

Used by AngularJS.org site

https://www.firebase.com/

Firebase Data Limits

A node's key max length 768

A node can't be nested deeper than 32 levels

Any unicode character except .$[]/ plus the ASCII control keys of 0-31 and 127

Firebase Sizes

One child value - 100 mb UTF-8 encoded

SDK write value max - 16 mb UTF-8

REST write value max - 100 mb UTF-8

Nodes in a read operation 100 million

Firebase Writing Dataset()

Saves data to the specified Firebase reference

Any existing data at the path is overwritten

update()

push()

transaction

Firebase Installation

Add script tag for firebase

Add script tag for AngularFire

Add firebase.json file

Create a firebase reference object

Lab - ng-contacts

We are going to super size the Todo app into a contacts

We will Firebase as our backend

We can develop locally and then deploy

Client-side Routing

Server-side routing vs client-side routing

ngRoute module

HTML URLs vs hash based URLs

Server vs Client side Routing

Traditionally changing the URL triggers server side request

This not the way single page apps (SPA) act

Angular watches $location.url() and tries to map it to a route definition

ngRoute

Provides routing and deep linking services and directives

Must include angular-route.js in HTML, after angular.js

Must mark ngRoute as a dependent module

HTML5 Push State vs Hash based URLs

By default Angular uses hash “#” based URLs

It can use HTML5 push state, with fallback

$locationProvider.html5Mode(true);

Directives

Introduction to Directives

jQuery integration

Using a jQuery UI Widget

Directives

Markers on a DOM element that attach a behavior to it

Can be an attribute, element name, comment, or CSS

The HTML compiler traverses the DOM at bootstrap and matches directives to DOM elements

Directives Names<div timePicker></div>

<div time-picker></div>

<div time:picker></div>

<div time_picker></div>

<div x-time-picker></div>

<div data-time-picker></div>

Directive Location

Tag name: <timePicker></timePicker>

Attribute: <div data-rnc-time-picker></div>

Class: <div class=“time-picker;”></div>

Comment: <!— directive:time-picker —>

Built-in Directives

ng-app

ng-bind

ng-controller

ng-href

ng-readonly

ng-repeat

ng-src

ng-submit

ng-transclude

ng-view

jQuery Integration

AngularJS includes a mini version of jQuery called jqLite

But it is perfectly compatible with the jQuery

jQuery must be loaded before Angular or it won’t see it

Filters

Understanding Filters

A tour of built-in filters

ngSanitize

Building custom Filters

Lab

Understanding FiltersUsed to format data displayed to user

Strictly front-end, doesn’t change model data

Accessible using declarative or imperative syntax

{{ expression [| filter_name[:parameter_value] ... ] }}

$scope.originalText = 'hello';$scope.filteredText = $filter('uppercase')($scope.originalText);

A tour of built-in filterscurrency

date

json

lowercase

uppercase

number

filter

limitTo

orderBy

Building custom filterstempApp.filter('minimum', [function () { return function (arrTemp, minimum) { var filteredArray = []; var min = minimum ? minimum : 15; angular.forEach(arrTemp, function (value, key) { if (value.temp >= min) filteredArray.push(value); }); return filteredArray; }; }]); !

Lab - Using Filters

Let’s add a search filter to our contacts app

ngSantize

Provides functionality to sanitize HTML

Parses the HTML into tokens

Safe tokens converted into properly escaped HTML strings

May be a bit overzealous

Using a jQuery Widgetapp.directive('timePicker', function () { var today = new Date(new Date().toDateString()); return { require: '?ngModel', link: function ($scope, $element, $attrs, ngModel) { var initialized = false; ngModel = ngModel || { "$setViewValue": angular.noop }; // where is the missing time value? setTimeout(function () { initialized = $element.timepicker() .on('changeTime', function (ev, ui) { var sec = $element.timepicker('getSecondsFromMidnight'); ngModel.$setViewValue(sec * 1000); console.log("sec = " + sec); }); }); ngModel.$render = function (val) { if (!initialized) { //If $render gets called before our timepicker plugin is ready, just return return; } $element.timepicker('setTime', new Date(today.getTime() + val)); } } }});

Lab - jQuery UI Widget

Let’s add a jQuery UI calendar widget to our contact app

We will essentially wrap it to make it “angularized”

SummaryModern Web Apps

Compared AngularJS’ way to jQuery’s

AngularJS’ Core Concepts

Controllers

Todo App

Contacts App

Summary

Firebase

Custom Directives

Filters

Integrating jQuery Widgets with AngularJS

Troy Miles

Over 30 years of programming experience

Blog: http://therockncoder.blogspot.com/

Twitter: @therockncoder

Email: rockncoder@gmail.com

GitHub: https://github.com/Rockncoder

Recommended