Post on 03-Aug-2015
Troy Miles
Over 35 years of programming experience
Blog: http://therockncoder.blogspot.com/
Twitter: @therockncoder
Email: rockncoder@gmail.com
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
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>
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
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
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/
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 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
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 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
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
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
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
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 “$”
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 rockncoder@gmail.com</p> <hr/> </script>
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);
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; }; }]);
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