Upload
troy-miles
View
985
Download
1
Embed Size (px)
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: [email protected]
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: [email protected]
GitHub: https://github.com/Rockncoder