Você está na página 1de 100

AngularJS End to End

Brad Green

#DV13-NGU

Brian Ford

Miko Hevery

Igor Minar

@angularjs

Building your First App


(basic concepts)
Brad Green
@bradlygreen

#DV13-NGU

@angularjs

Setup: Template
< htm lng-app= 'coolApp'>

< body>

< script src= 'angular.js'> < /script>


< script src= 'coolApp.js'> < /script>
< /body>
< /htm l>
#DV13-NGU

@angularjs

Setup: JS

var m yApp = angular.m odule('coolApp', []);

#DV13-NGU

@angularjs

Principles

Boilerplate

D.R.Y.

#DV13-NGU

Structure

Testability

@angularjs

Structure: Model-View-Controller
<div>
<span>

<ul>

<li>

View
(DOM)

Observes

Notifies

RAM

Model
(JS Objects)

Manages
Controller
(JS Classes)

#DV13-NGU

@angularjs

Model:
View:

{ "nam e": "M isko" }

< p ng-controller= 'PersonController as person'>


H i, {{person.m odel.nam e}}
< /p>

Controller:

m yApp.controller('PersonController', function () {
this.m odel= { nam e: 'M isko' };
});

#DV13-NGU

@angularjs

Model:
View:

{ "nam e": "M isko" }

< p ng-controller= 'PersonController as person'>


H i, {{person.m odel.nam e}}
< /p>

Controller:

m yApp.controller('PersonController', function (s) {


this.m odel= s.getPerson();
});

#DV13-NGU

@angularjs

Feature: Data Binding


hello.js
this.greeting = 'H ola!';

hello.html
{{ greeter.greeting }}

// 1-w ay

< input ng-m odel= 'greeter.greeting'> // 2-w ay

#DV13-NGU

@angularjs

Note: Binding for initial page load


Markup fine except for first page
< p> {{som eO bj.som ething}}< /p>

Use ng-cloak to avoid unstyled content on load


< p n g -cloak> {{som eO bj.som ething}}< /p>

Attribute form also avoid unstyled content on load


< p n g -b in d = 'som eO bj.som ething'> < /p>
#DV13-NGU

@angularjs

Feature: Directives
< div n g -rep eat= 'item in cart.item s'>
< span n g -b in d = 'item .nam e'> < /span>
< button n g -click= 'cart.delete($index)'>
D elete
< /button>
< /div>
#DV13-NGU

@angularjs

Note: Directive validation


< div d ata-ng-repeat= 'item in cart.item s'>
< span d ata-ng-bind= 'item .nam e'> < /span>
< button d ata-ng-click= 'cart.delete($index)'>
D elete
< /button>
< /div>
#DV13-NGU

@angularjs

Feature: Dependency Injection


Definition
function M yFoo() { };
m odule.service('foo', M yFoo);
Usage
function M yBar(foo) {
Foo instanceof M yFoo; // true!
}
#DV13-NGU

@angularjs

Preferred usage
m yApp.service('foo', function() {
...
});

#DV13-NGU

@angularjs

Principle: Eliminate boilerplate


Dependency Injection
POJO Models
No DOM in most code paths

#DV13-NGU

@angularjs

View Templates
Directives
Markup {{ }}
Form Validation
Filters

#DV13-NGU

@angularjs

Filters
< p> {{ invoice.total| currency }}< /p>

#DV13-NGU

@angularjs

Filter example: Reverse


m yApp.fi
lter('reverse', function() {
return function(input) {
var out = '';
for (var i= 0; i< input.length; i+ + ) {
out = input.charAt(i) + out;
}
return out;
}
});

#DV13-NGU

@angularjs

Back to Controllers
Thus far:
Expose model to view
Expose functions to handle user interaction
Update model to change the view
But also:
Instantiated once per use in your template
Can request $scope
#DV13-NGU

@angularjs

$scope
You can request $scope in controllers
m yApp.controller('G reetCtrl', function ($scope) {
$scope.greeter = { greeting: 'M isko'};
});

Use in template
< p ng-controller= 'G reetC trl'> {{greeter.greeting}}< /p>

#DV13-NGU

@angularjs

$scope
Context for expression evaluation
Hierarchical, mirroring your DOM structure
Prototypal inheritance = global read, local write

#DV13-NGU

@angularjs

$scope
$watch(expression, callback): Executes a callback
whenever a given expression changes
$apply() : synchronize data binding from outside
Angular's event loop

#DV13-NGU

@angularjs

Expressions
{{ The stuff inside your markup }}
ng-bind='and inside directives'
Like JavaScript, but eval'd against your $scope
No complex logic like loops or throws
Though terinary operator is supported

#DV13-NGU

@angularjs

Expression Examples
person.name
shoppingCart.total()
cart.total() - user.discountRate

#DV13-NGU

@angularjs

Talking to servers
$h ttp : HTTP server communication
$resou rce: RESTful server communication
Notable other options:
Restangular
AngularFire
BreezeJS

#DV13-NGU

@angularjs

$http
this.som eD ata = $http.get('/som eU rl');

#DV13-NGU

@angularjs

$http
$http.get('/som eU rl').
success(function(data, status, headers, confi
g) {
// called asynchronously
}).
error(function(data, status, headers, confi
g) {
// called if an error occurs, also async
});

#DV13-NGU

@angularjs

Promises
$http.post('/user/', user).th en (
function() {
alert('Successfully created user!');
}, function() {
alert('Error creating user...');
}
);
#DV13-NGU

@angularjs

Routes

Left Nav

Header

#DV13-NGU

Content View

@angularjs

Routes
< n g -view > directive as content placeholder
$rou teP rovid er to configure:
Controller
Template
URL

#DV13-NGU

@angularjs

Routes
m yApp.confi
g (function($routeProvider) {
$routeProvider.w hen('/inbox', {
tem plateU rl: 'inbox.htm l',
controller: 'InboxCtrl',
controllerAs: 'inbox'
});
});

#DV13-NGU

@angularjs

Putting it all together

#DV13-NGU

@angularjs

Resources
Tools

Batarang

#DV13-NGU

UI Components

Libraries

Books

Bootstrap

@angularjs

Learning Resources

docs.angularjs.org
/tutorial

#DV13-NGU

egghead.io

thinkster.io

pluralsight.com

@angularjs

Questions?
#DV13-NGU

@angularjs

Internals of AngularJS
(How it all works)
Miko Hevery

#DV13-NGU

@angularjs

Data Binding

Goal: Separate code from HTML

#DV13-NGU

@angularjs

Data Binding
<div>

Model

Drives

<span>

<ul>
<li>
<li>
<li>

<div>

Model

Depends on

<span>

<ul>
<li>
<li>
<li>

#DV13-NGU

@angularjs

Data Binding: Requirements

Model is a Plain-Old-JavaScript-Object
Detect value changes
Easily describe value in the model
Encapsulate DOM access

#DV13-NGU

@angularjs

Scope

Goal: Provide context for expressions

#DV13-NGU

@angularjs

Scope
User = function () {
this.fullName = 'Miko Hevery';
this.username = 'mhevery';
}
scope = {};
scope.user = new User();
{{user.fullName}}
{{user.username}}
#DV13-NGU

@angularjs

Scope
{{name}}
<ul>
<li ng-repeat="name in names">
{{name}}
</li>
</ul>

#DV13-NGU

@angularjs

Scope
parent = {};
child = inherit(parent);
parent.name = 'parent';
expect(child.name).toEqual('parent');
child.name = 'child');
expect(child.name).toEqual('child');
expect(parent.name).toEqual('parent');
#DV13-NGU

@angularjs

Scope
function inherit(parent) {
function C() {}
C.prototype = parent;
return new C();
}
parent = {};
child = inherit(parent);
expect(child.__proto__).toBe(parent);
#DV13-NGU

@angularjs

Scope
{{name}}
<ul>
<li ng-repeat="name in names">
{{name}}
</li>
</ul>

#DV13-NGU

@angularjs

Watchers

Goal: Notify of model changes

#DV13-NGU

@angularjs

Watchers
{{name}}
scope.name = 'Miko Hevery';
scope.$watch('name', function(value) {
element.text(value);
});

#DV13-NGU

@angularjs

Digest Cycle

Goal: Non-intrusive change detection

#DV13-NGU

@angularjs

Digest Cycle
scope.$watch('name', reactionFn);

#DV13-NGU

var lastValue;
function dirtyCheck() {
var value = scope.name;
if (lastValue != value)
reactionFn(value);
lastValue = value;
}

@angularjs

Digest Cycle
scope.$watch('count', function(value) {
alert(value);
});
scope.$watch('name', function(value) {
scope.count++;
});
#DV13-NGU

@angularjs

Digest Cycle

Goal: Knowing when to digest

#DV13-NGU

@angularjs

Digest Cycle

#DV13-NGU

@angularjs

Digest Cycle: Sync vs Async


var result1 = cacheApi(function() {
result1.doSomething();
});

API should not mix sync/async


Need a way to simulate async callbacks
setTimeout(0) is problematic
#DV13-NGU

@angularjs

Digest Cycle: Sync vs Async


StackFrame
#3
#2
#1
#0

#DV13-NGU

asyncApi()
yourApplicationBehavior()
ng.$apply()
nativeCode(event)

@angularjs

Expressions

Goal: Code of least surprise

#DV13-NGU

@angularjs

Expressions
{{user.firstName}}
eval('with(scope){return
user.firstName;}');
if (scope.user) {
return scope.user.firstName;
}
#DV13-NGU

@angularjs

Expressions

eval() can not be the solution


silent dereference
executes in global context
CSP
Security

#DV13-NGU

@angularjs

Expressions

Let's think out of the box


Let's implement JavaScript in JavaScript
Full lexer and parser implies full control over:
Syntax
Semantics

#DV13-NGU

@angularjs

Directive

Goal: Express intent in HTML

#DV13-NGU

@angularjs

Directive
<ul>
<li ng-repeat="user in users">
{{user.name}}
</li>
</ul>

#DV13-NGU

@angularjs

Directive
scope.$watch('name', function(value) {
element.text(value);
});

<span ng-bind="name"></span>

#DV13-NGU

@angularjs

Compiler

Goal: extend HTML syntax


(teach browser new tricks)

#DV13-NGU

@angularjs

Compiler
<div ng-controller="MyCtrl as c">
<div ng-repeat="name in c.names">
{{name}}</div>
</div>

Traverse the DOM => locate directives, remember


location
Template: Easily apply directives to DOM clone
#DV13-NGU

@angularjs

Dependency Injection

Goal: Get rid of setup code

#DV13-NGU

@angularjs

Dependency Injection
function Door() {}
function House(door) {}
function App(house) {}
// implied
app = new App(new House(new Door)));

#DV13-NGU

@angularjs

Dependency Injection

How do you know what to inject?

#DV13-NGU

@angularjs

Dependency Injection
function Door() {}
function House(door) {}
House.$inject = ['door'];
function App(house) {}
App.$inject = ['house'];
#DV13-NGU

@angularjs

Dependency Injection
describe('something', function() {
function test($rootScope){}
test.$inject = ['$rootScope'];
it('should ...', test);
});

#DV13-NGU

@angularjs

Dependency Injection
function House(door) {}
House.$inject =
creazyRegExp(House.toString());

#DV13-NGU

@angularjs

Dependency Injection
function Door(){}
function House(door) {}
injector = new Injector(...);
house = injector.instantiate(House);

#DV13-NGU

@angularjs

Dependency Injection
function instantiate(Type) {
var args = Type.$inject.map(instantiate);
return new Type.call(args);
}

#DV13-NGU

@angularjs

Dependency Injection

Add Caching, Modules and


some syntactic sugar and
you have full DI system

#DV13-NGU

@angularjs

Routing

Goal: Preserve the web paradigm

#DV13-NGU

@angularjs

Routing

Deep linking
Links work like links
Support HTML5 pushstate
URL rewriting

#DV13-NGU

@angularjs

Routing
<a href="/chapter/{{id}}">
http://server.com/chapter/123
http://server.com/#!/chapter/123

Server cooperation needed


#DV13-NGU

@angularjs

REST

Goal: Easy server communication

#DV13-NGU

@angularjs

REST

Make common case simple


Take advantage of data-binding
Future / Promises

#DV13-NGU

@angularjs

REST
Chapter = $resource('/chapter/:chapterId');
var chapters = Chapter.query();
<div ng-repeat="chapter in chapters">
{{chapter.name}}
</div>

#DV13-NGU

@angularjs

Questions?
#DV13-NGU

@angularjs

The New Stuff

(animations, track by, controller as,


security, error messages)
Brian Ford and Igor Minar

#DV13-NGU

@angularjs

Animations in Angular
Animations are a natural
extension of CSS3 animations
and AngularJS directives
#DV13-NGU

@angularjs

Animations in Angular

Angular automatically coordinates DOM


operations, so you can focus on the
visuals of the animation.

#DV13-NGU

@angularjs

Animations
// HTML
<div ng-repeat="item in list" class="item">{{item}}</div>

//CSS
.item.ng-enter, .item.ng-move {

.item.ng-leave {

transition:0.5s linear all;


opacity: 0;

animation: 0.5s my_animation;


}

}
@keyframes my_animation {
.item.ng-enter.ng-enter-active,

from { opacity:1; }

.item.ng-move.ng-move-active {

to { opacity:0; }

opacity: 1;

}
#DV13-NGU

@angularjs

Animation Hooks

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

#DV13-NGU

@angularjs

Animation in Action
Example App: https://github.com/matsko/ngconf-animations-demo

#DV13-NGU

@angularjs

Animation (& Touch) in Action


Example: Sidebar

ngIf
ngSwipeLeft/Right

https://github.com/btford/brian-talks-about-animations
#DV13-NGU

@angularjs

Animation in Action
Example: Slideshow

ngView

https://github.com/btford/brian-talks-about-animations
#DV13-NGU

@angularjs

Animation in Action
Example: Notifications

ngRepeat

https://github.com/btford/brian-talks-about-animations
#DV13-NGU

@angularjs

Animation Best Practices


With great power comes great responsibility

Be tasteful

They should enhance UX

use sparingly
same functionality, but better affordances

Keep them fast


http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/

#DV13-NGU

@angularjs

Animation and track by

(ng-repeat)

ng-repeat is stable
Database data needs to be refreshed
<div ng-repeater="o in objs track by o.id">
...
</div>

#DV13-NGU

@angularjs

"Controller As"
Before:
<div ng-controller="UserController">
<p>{{name}}</p>
<div ng-if="someCondition">
<input ng-model="name">
</div>
</div>
#DV13-NGU

@angularjs

"Controller As"
Unambiguously bind to models:
<div ng-controller="UserController as
user">
<p>{{user.name}}</p>
<div ng-if="someCondition">
<input ng-model="user.name">
</div>
</div>
#DV13-NGU

@angularjs

Security Enhancements

#DV13-NGU

Template origin verification


Expression sandbox hardening
Better Content Security Policy support
SCE

@angularjs

SCE (strict contextual auto-escaping)


<input ng-model="userHtml">
<div ng-bind-html="userHtml">

#DV13-NGU

@angularjs

SCE (strict contextual auto-escaping)


var htmlSrc = '<div>...</div>';
var htmlWrapper = $sce.trustAsHtml(htmlSrc);
var htmlDst = $sce.getTrustedHtml(htmlWrapper);

#DV13-NGU

@angularjs

Improved Error Messages

Before:

Uncaught Error: No module: ngResource

After:
Uncaught Error: [di-nomod] Module 'ngResource' is not
available! You either misspelled the module name or
forgot to load it.
http://docs.angularjs.org/error/di-nomod?a=ngResource

In production:
Uncaught Error: [di-nomod] ngResource
http://docs.angularjs.org/error/di-nomod?a=ngResource
#DV13-NGU

@angularjs

m inErr - Improved Error Messages


[$rootScope:infdig] http://...?p0=10&...

#DV13-NGU

@angularjs

More Angular!
Between 1.0.0 and 1.2.0 ...
1,575 SHAs/PRs
2,850 Issues closed

Direc
tory

*
#DV13-NGU

LOC
Added

LOC
Remo
ved

101,489

36,938

LOC
Total

@angularjs

Even Moar Angular!

#DV13-NGU

What

W When
h
er
e

Advanced
AngularJS
Workshop

B
O
F
1

Unit testing
JavaScript /
CoffeeScrip
t / Dart
code with

R Tue
o 17:25 o 17:55
m
8

Mon
13:30 16:30

@angularjs

Questions?
#DV13-NGU

@angularjs

Você também pode gostar