angular js crash course 140501021644 phpapp01
DESCRIPTION
angularTRANSCRIPT
Crash Course
Keith BloomfieldLead Developerdev9
Crash Course
Crash Course
Show of HandsFront-end developers?Back-end developers?Other?Using AngularJs at work/home?New to AngularJs?
Keith BloomfieldLead Developerdev9
OverviewData Binding, Expressions, Scopes,Ng DirectivesModules, Dependency InjectionControllers, Services, Factories, DirectivesUnit TestingEnd-to-End (e2e) TestingContinuous IntegrationReal World ExperiencesTool SupportResources for LearningQ&A
Crash Course
Agenda
Overview
AngularJs is a Spa framework
Manicure/Pedicure
Body/Facial Treatment
Massage
A lot has changed on the front-end in the lastfew years!
Overview
AngularJs is a Spa framework
Single-Page Application (dynamic views)
Recommends client-side Model-View-Controller (Mvc) pattern
Overview
AngularJs is a Spa framework
Single-Page Application (dynamic views)
Recommends client-side Model-View-Controller (Mvc) pattern
Don't know about each other.
Overview
AngularJs is a Spa framework
Single-Page Application (dynamic views)
Recommends client-side Model-View-Controller (Mvc) pattern
Overview
AngularJs is a Spa framework
Single-Page Application (dynamic views)
Recommends client-side Model-View-Controller (Mvc) pattern
Implications:RoutingHistoryCaching PackagingDeploymentAutomationData BindingObject ModelingTiming/DispatchTemplatingTestingStorage...
AngularJs
Overview
AngularJs is a Spa framework
Single-Page Application (dynamic views)
Recommends client-side Model-View-Controller (Mvc) pattern
What becomesof this?
Overview
AngularJs is a Spa framework
Single-Page Application (dynamic views)
Recommends client-side Model-View-Controller (Mvc) pattern
Model-View-Whatever (Mvw)
The View
Templates/Partials
foo.htmlHtml content swapped into/out of the single page
my-app.htmlmy-header.htmlmy-cart.htmlmy-news.htmla2.htmla2.htmlbn.htmlc1.htmla1.htmla3.htmlb3.htmlb2.htmlb1.htmlc2.htmld.htmlmy-mail.html
my-tools.html
Data Binding, Expressions and Scopes
Extending Html's vocabulary: Directives
Extend Html as markers on the Dom
Can be used as an attribute, element, class name, comment
Tell AngularJs' compiler ($compile) to attach specific behavior to that Dom element or even transform that element and its children.
echo
Name:
{{ echo }}
Angular (ng)Directives
Data BindingExpression
The compilation is a process of walking the DOM tree and matching DOM elements to directives. (links scope to template)
auto-bootstraps the AngularJs application/designates the root element.
binds input, select, textarea to aproperty on the scope using ng-model(NgModelController), and more.
Evaluated againstthe scope.
Data Binding, Expressions and Scopes
Extending Html's vocabulary: Directives
Extend Html as markers on the Dom
Can be used as an attribute, element, class name, comment
Tell AngularJs' compiler ($compile) to attach specific behavior to that Dom element or even transform that element and its children.
Data Binding, Expressions and Scopes
Extending Html's vocabulary: Directives
The only place where an AngularJs application touches the Dom is within directives.
This is good as artifacts that access the Dom are difficult to test.
More about directives later, but first...
Data Binding, Expressions and Scopes
$scope
Acts as the glue between the view and the controller
Refers to the application model
Arranged hierarchically to mimic the Dom
Can inherit from parent scope
Can watch expressions and propagate events
Data Binding, Expressions and Scopes
$scope
$rootScope: Defined at the top level of the application (where the ng-app directive is applied)
Lookup proceeds up the scope chain when a variable is not found in the local scope.
Relying on scope is risky because the Dom layout is often changed. - Isolating scope protects against changes to the Dom hierarchy.
Data Binding, Expressions and Scopes
$scope
$watch: Observe model mutations
$apply: Propagate model changes through the system into the view from outside the Angular realm (controllers, services, ng event handlers). Triggers $digest, which can be used directly in unit tests.
Also available: $watchCollection, $destroy, $eval, $evalAsync, $on, $emit, $broadcast
Dependency Injection
Reusable container for different features of your app
Module
Dependency Injection
Has two phases:config: setup providers and constants
run: after injector is created, kickstart the app
angular.module('myModule', ['moduleDependency1', 'moduleDependency2',....]).config(function(injectable1, injectable2,...) { // provider-injector// Use as many of these as you want.// Can only inject Providers (not instances)}).run(function(injectable1, injectable2,....) { // instance-injector// Use as many of these as you want.// Can only inject instances (not Providers) and constants});
Module
Dependency Injection
Module
Features can be bundled and injected in/as modules
Dependency Injection
$provide
- Object in module auto
auto- Implicit module which gets automatically added to each $injector
$injector- used to retrieve object instances as defined by provider, instantiate types, invoke methods, and load modules.
Dependency Injection
$provide
- Helper methods (also exposed on module):
provider(provider) - registers a service provider with the $injector
constant(obj) - registers a value/object that can be accessed by providers and services.
value(obj) - registers a value/object that can only be accessed by services, not providers.
factory(fn) - registers a service factory function, fn, that will be wrapped in a service provider object, whose $get property will contain the given factory function.
service(class) - registers a constructor function, class that will be wrapped in a service provider object, whose $get property will instantiate a new object using the given constructor function.
Worth investigating: $provide.decorator() // $provide onlyhttps://egghead.io/lessons/angularjs-provide-decorator
Dependency Injection
$provide
- Helper methods (also exposed on module):
provider(provider) - registers a service provider with the $injector
constant(obj) - registers a value/object that can be accessed by providers and services.
value(obj) - registers a value/object that can only be accessed by services, not providers.
factory(fn) - registers a service factory function, fn, that will be wrapped in a service provider object, whose $get property will contain the given factory function.
service(class) - registers a constructor function, class that will be wrapped in a service provider object, whose $get property will instantiate a new object using the given constructor function.
Where is the Controller?Added to the Dom using ng-controller
The ng-controller directive asks the injector to create an instance of the controller and its dependencies.
The controller itself never knows about the injector.
Loose coupling is maintained.
Dependency Injection
Dependencies are looked up by name for a provider that satisfies the argument.
app.controller(AController, function($scope, $http){$scope.userName = 'Walt';$scope.foo = $http.get('http://foo.com');});
a.controller(AController, function(b, c){b.userName = 'Walt';b.foo = c.get('http://foo.com');});
Minified:
Order doesn't matter$scope found inng module - $rootScopeProvider- $rootScope.Scope$http service found ng module- $http
OH NO!
Dependency Injection
Longer version preserves dependency by treating it as an argument:
app.controller(AController, ['$scope', '$http', function($scope){$scope.userName = 'Walt';$scope.foo = $http.get('http://foo.com');}]);
a.controller(AController, ['$scope', '$http', function(b, c){b.userName = 'Walt';b.foo = c.get('http://foo.com');}]);
Minified:
Order matters
Passed in as argumentsto the function
Dependency Injection
Minification Pain Relief: ngminhttps://github.com/btford/ngmin
It turns thisangular.module('whatever').controller('MyCtrl', function ($scope, $http) { ... });into thisangular.module('whatever').controller('MyCtrl', ['$scope', '$http', function ($scope, $http) { ... }]);
Controllers
Used to augment the Angular scope
Attached to the Dom via the ng-controller directive
Set up the initial state of the $scope object
Add behavior to the $scope object
Our Pizzas:
{{ pizza.name }}...
app.controller('HomeController', function($scope){
$scope.pizzas = [{name: "Meat Lover's",ingredients: ['Sausage','Pepperoni','Bacon','Olives'],price: 6},{name: 'Hawaiian',ingredients: ['Canadian bacon','Pineapple'],price: 5},];});
!Controllers
Do not use a controller to:
Manipulate the Dom- Business logic only. Presentation logic affects testability and belongs in directives
Format input- Use angular form controls instead: https://docs.angularjs.org/guide/forms
Filter output- Use angular filters instead: https://docs.angularjs.org/guide/filter
Share code or state across controllers- Use angular services instead: https://docs.angularjs.org/guide/services
Manage the life cycle of other components- eg: Using a controller to create a service instance
Services
Stateless, injectable argument providing the instance of a function passed to module.service
Singleton: delayed/lazy loaded (Not instantiated until used), only instantiated once
Good for cross app/controller communication (sharing of utility functions)
service(class) - registers a constructor function, class that will be wrapped in a service provider object, whose $get property will instantiate a new object using the given constructor function.
Factories
servicefactory
module.service('MyService', function() {this.method1 = function() {//..}
this.method2 = function() {//..}});module.factory('MyService', function() {
var factory = {};
factory.method1 = function() {//..}
factory.method2 = function() {//..}
return factory;});
factory(fn) - registers a service factory function, fn, that will be wrapped in a service provider object, whose $get property will contain the given factory function.
Services, Factories, Values, Constants
Are convenience methods for making providers
Serve to avoid polluting the global namespace
Services, Factories, Values, Constants
The difference between factory and service is the difference between a function and an object.
Factory(give it a function)
Service(give it a constructor)
Further study (object vs. function):http://stackoverflow.com/questions/1646698/what-is-the-new-keyword-in-javascript
Further study (ng factory vs. service):http://iffycan.blogspot.com/2013/05/angular-service-or-factory.htmlhttps://www.youtube.com/watch?v=A6cJasNBkyI
service vs. factory
Services, Factories, Values, Constants
Either can be a primitive, object, or function
Constant can be injected into services, controllers, or module configs
Value can only be injected into services and controllers
value vs. constant
Why can't value be injected into module config?
The injector has not been setup yet.Constants (special case) are accessed by their name alone, cannot be changed, and aren't accessed through a provider $get.
Services, Factories, Values, Constants
Are convenience methods for making providers
You can also create your own providers:
app.config(function($provide){$provide.provider('MyProvider',{$get: function(){return{foo: function(){return 'bar';}}}}) });
Services, Factories, Values, Constants
function provider(name, provider_) {assertNotHasOwnProperty(name, 'service');if (isFunction(provider_) || isArray(provider_)) {provider_ = providerInjector.instantiate(provider_);}if (!provider_.$get) {throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);}return providerCache[name + providerSuffix] = provider_;}
function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
function service(name, constructor) {return factory(name, ['$injector', function($injector) {return $injector.instantiate(constructor);}]);}
function value(name, val) { return factory(name, valueFn(val)); }
function constant(name, value) {assertNotHasOwnProperty(name, 'constant');providerCache[name] = value;instanceCache[name] = value;}
Source:
Directives
Isolate Scope: Directive-specific scopeAssists in creating reusable components
Prevents or other components from changing your model state
app.controller("myController", function($scope){$scope.doSomething = function(something){...};}).directive('myDirective', function () {
return {restrict: "E",scope:{done:"&"},template:'my-template.html'}});
The 'scope' optionisolates the directive'sscope.
Directives
Directive Definition Options: Instructions to the ng compiler
app.controller("myController", function($scope){$scope.doSomething = function(something){...};}).directive('myDirective', function () {
return {restrict: "E",priority:sort order before compilation, terminal: if true, process this directive last,scope: true, false, or {} (isolate)controller: instantiate before pre-linking phase...,require:..another directive and inject its controller...controllerAs:controller alias at the directive scope...type: doctype ('html','svg','math'),template:replace current element with....templateUrl: same as above, but async from url...replace: where to insert template...,transclude: precompile element.....,compile: transform template Dom...,link: update Dom, register listeners...,}
restrict:matching restrictionoptions:'A' - only matches attribute name'E' - only matches element name'C' - only matches class name'M' - only matches comment
or any combination.(eg: 'AE')
default: 'A'
Directives
Directive Definition Options: Instructions to the compiler
app.controller("myController", function($scope){$scope.doSomething = function(something){...};}).directive('myDirective', function () {
return {restrict: "E",priority:sort order before compilation, terminal: if true, process this directive last,scope: true, false, or {} (isolate)controller: instantiate before pre-linking phase...,require:..another directive and inject its controller...controllerAs:controller alias at the directive scope...type: doctype ('html','svg','math'),template:replace current element with....templateUrl: same as above, but async from url...replace: where to insert template...,transclude: precompile element.....,compile: transform template Dom...,link: update Dom, register listeners...,}
Deferring to api:https://docs.angularjs.org/api/ng/service/$compile#description_comprehensive-directive-api_directive-definition-object
Unit Testing
Test on real devices
Remote control
Testing framework agnostic (Jasmine, Mocha, QUnit... or write adapter)
Simple CI integration (Jenkins, Travis, Semaphore)
Open Source
Easy to debug from IDE
Karma
End-to-End (e2e) Testing
Protractor
Thin wrapper for webdriver.js
Support for cross-browser testing using Selenium Webdriver
Support for GhostDriver/PhantomJs (Wip)
Includes webdriver-manager for drivers, Selenium installation, and updates to both
Includes elementExplorer for building locators
Integrates with Saucelabs, easy enough to port over to BrowserStack
End-to-End (e2e) Testing
Protractor
Recommends the Page Object Model design pattern for testing
End-to-End (e2e) Testing
Protractor
var flow = browser.driver.controlFlow();
// pseudocodelogin = function(username){...}navigateToReviews = function(){...}addNewReview = function(){...}
flow.execute(login('Walt'));flow.execute(navigateToReviews);flow.execute(addNewReview);
(Optional) Tap into webdriver.js:
Continuous Integration
Jenkins + NodeJs plugin
Unit tests run via Grunt and Karma
e2e tests are still a work-in-progress:Rely on npm concurrent, connect(express), scripts for setup + watch and teardown
Awaiting reintroduction of timing in Jasmine for PhantomJs tests
Awaiting Saucelabs/BrowserStack credentials for cross-browser tests
Real World Experiences: Project Challenges
Project challenges are similar to those of all large projects:Discovering and establishing best practices amongst contributors
Directory structures/file taxonomy, refactoring with project growth
Keeping libraries up do date, Bower in the loop
Rediscovery of conveniences found in mature frameworks
Multiple solutions, evaluation, and selection
Real World Experiences: New Challenges
Adjustments for allRamp up on new framework and conceptsContinuous delivery and deployment challenges (binary artifacts, externalizing conf)Various tools/tools in motion (grunt, node/npm, bower, css compilers, yeoman)
Front-end veteransNew conventions, structures, design patterns (not just jquery, js, css any more)More responsibility for application architecture
Back-end veteransJavascript as the primary language (callbacks, promises, debugging, refactoring..)UX, responsiveCoordination with rest apis and content delivery service
Real World Experiences:Gotchas
Potential for memory leaks/weird behavior with scope misuse
Bower gone wild
Dependency additions, revisions (npm need-to-know)
Library/dependency bloat
Issues/feature requests in (ng and integrated) libraries and tools
Tool Support: IDEs & Refactoring
IntelliJ Idea, WebStorm
Vim, SublimeText
Netbeans
Visual Studio
Behold thePlug-Ins!
Tool Support: Misc. Open Source Frameworks
Yeoman (Yo, Grunt, Bower) + generatorshttp://yeoman.io/
Lots of Grunt plugins
Lots of Npm packages
Batarang plugin for Chrome
Browser web developer console
Tool Support: Static Code Analysis
JsHint: http://www.jshint.com/
grunt-contrib-jshint:https://github.com/gruntjs/grunt-contrib-jshint
Enforces code quality using rules
Configured tasks in grunt pass directly to jshint
Customizable reporter output,
options and globals
ignores for specific warnings
grunt-contrib-concat: Linting before and after concatenating files
Tool Support: Code Coverage
Karma + Istanbul: karma-coveragehttps://github.com/karma-runner/karma-coverage
Generates reports in several formats including Cobertura xml (integration with Jenkins)
Protractor (none, lots of unit tests, REST apis covered on their end)
Resources for Learning
stackoverflow
angularjs.org
AngularJs api docs: https://docs.angularjs.org/api
github (docs, plunkers, demos)
egghead.io (free and subscription)
AngularJs Style Guide:https://google-styleguide.googlecode.com/svn/trunk/angularjs-google-style.html
angular-phonecat tutorial:http://docs.angularjs.org/tutorial
Los Techies AngularJs: http://lostechies.com/gabrielschenker/2014/02/26/angular-js-blog-series-table-of-content/
Q&A
Demo examples: https://github.com/kthblmfld/angularjs-from-scripts