Beginning AngularJS Enterprise

89
Beginning AngularJS 17 & 18 June 2015, Broadbean Troy Miles

Transcript of Beginning AngularJS Enterprise

Beginning AngularJS17 & 18 June 2015, Broadbean Troy Miles

Troy Miles

Over 35 years of programming experience

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

Twitter: @therockncoder

Email: [email protected]

GitHub: https://github.com/Rockncoder

Agenda Day One

Introduction

Tools

Using Yeoman

To Do App

Testing

Animation

Services/Modules

Form Validation

Controller As

Filters

Agenda Day Two

Deployment

Providers

Contacts App

$http & Promises

$resource

Testing ajax calls

Custom Directives

Wrap-up

Setup Check

Lab #1 - Setup Check

In the labs 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

Lab #2 - jQuery BindingFrom the labs 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 Right with jQuery?

jQuery is a very popular library

It is used on 50% of all web sites

Makes it DOM manipulation and ajax easy

What’s Wrong with jQuery

It is a library not a framework

It encourages mixing of UI and logic

Resulting code can be very difficult to test

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>

Introducing AngularJS

Other JavaScript MVC Frameworks

Backbone.js

Knockout

EmberJS

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)

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

How popular is AngularJS?

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

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

AngularJS is testing framework agnostic

It supports both unit and integration tests

For unit tests it works well with Jasmine

Karma is the test runner

Tools

npm

Included with Node.js

Installs many open source projects

https://www.npmjs.com/

Yeoman

Kickstarts a new project

Adheres to best practices

Uses Generators

http://yeoman.io/

Bower

Package manager for web applications

Keeps track of your libraries like jQuery, Bootstrap, etc

Dependencies kept in bower.json file

http://bower.io/

Grunt

JavaScript Task Runner

Does mundane work for you

Hundreds of plugins available

http://gruntjs.com/

Directives

AngularJS Directives

ng-app

ng-controller

ng-model

ng-bind

ng-repeat

ng-if

ng-switch

ng-include

ng-view

ng-src / ng-href

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' />

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

HTML permits dashes and colons, JavaScript 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

Lab #3 - Greet-o-matic

Open the greet-o-matic.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>

Strict Mode

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

Strict Mode

No implicit global variables

No octals

No duplicate object keys

No with statement

arguments and eval simplified

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

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

Using Yeoman

npm install -g yo bower grunt-cli grunt

npm install -g generator-angular

yo angular

Code Along - Todo App Steps

Create todo directory

yo angular

create todo controller

create todo view

create todos array

create add method

create delete method

create local storage service

persist to local storage

Animation

Animation Types

CSS Transitions

CSS Animations

JavaScript Animations

Animation Events

enter - DOM element added

leave - DOM element removed

addClass - A class is added to an element

removeClass - A class is removed from an element

move - The element changes position

Animation Resources

https://docs.angularjs.org/guide/animations

http://www.nganimate.org/

Jasmine + Karma

Jasmine

Latest version 2.2, but we will be using 2.0.2

The default unit tester for AngularJS

Others will also work

Behavior Driven Development (BDD) approach

TDD vs BDD

Dev writes test

Run tests - fail

Implement tests in code

Run tests - pass

Refactor code

Dev writes behavior and specs

Run specs - fail

Implement specs in code

Run specs - pass

Refactor code

Describe - test suite

Describe is a global jasmine function

Two params

string - name of the test suite

function - implementation of the suite

Can be nested

it - specs

it is a global jasmine function

Looks like describe

A spec contains one or more expectations

If all expectations true, it is a passing spec

If any expectation fails, it is a failing spec

Expectations

Expect function

One param

The actual

Chained to a Matcher function

Matchers

Take the output of the expect function and compare it to something

Implement a boolean compare between actual value and expected

Reports to Jasmine if the expectation is true or false

Any matcher can be negated with a not before it

Some matchers

toBe - compares using ===

toEqual - works for literal variables and objects

toMatch - for regular expressions

toBeDefined - compares against 'undefined'

toBeUndefined - also compares against ‘undefined'

Some matchers (CONTINUE)

toBeNull - compares against null

toBeTruthy - truthy boolean casting

toBeFalsy - falsy boolean casting

toContain - finds an item in array

Some matchers (CONTINUE)

toBeLessThan

toBeGreaterThan

toBeCloseTo - precision math comparison

toThrow - should throw an exception

beforeEach / afterEachAre setup and teardown functions

called before and after each spec it

this

beforeEach, it, and afterEach share the same this

it is cleared before call spec call

any beforeEach not included in a describe block is executed before any Jasmine test

can use this to add custom matchers

Disabling suites and specs

prepend an 'x' before describe or it

specs inside a disabled suite are not ran

Unit Testing 3As

Arrange - Set up object to be tested

Act - Act on the object

Assert - Test the state of the object

Karma

A JavaScript test runner

Testing framework agnostic

Can be configured to use real browsers & devices

Can be integrated into continuous integration

Open source and from Google

Providers

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 “$”

Code Along - Contacts

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

Views

template - String contain HTML to display

templateUrl - Relative URL of file holding HTML or id of DOM element holding HTML

Inline View TemplateThe id name in the script tag matches…

templateUrl value of the route

template stored in index.html or other HTML file

74

<script id="contact.html" type="text/ng-template"> <h2>Contact</h2> <hr/> <p>For more information email [email protected]</p> <hr/> </script>

Filters

Understanding Filters

A tour of built-in filters

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

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

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)); } } }});

Code Along - Directives

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

Custom Directives

Filters

Integrating jQuery Widgets with AngularJS