0% found this document useful (0 votes)
109 views97 pages

Angular University Devoxx 2013

The document provides an overview of building a first AngularJS app, covering basic concepts like setting up templates and controllers, using directives for data binding and repeating elements, making requests to servers, and implementing routing and REST services to retrieve and display data. Key principles of AngularJS like dependency injection, scopes, watches, and expressions are also explained at a high level.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
109 views97 pages

Angular University Devoxx 2013

The document provides an overview of building a first AngularJS app, covering basic concepts like setting up templates and controllers, using directives for data binding and repeating elements, making requests to servers, and implementing routing and REST services to retrieve and display data. Key principles of AngularJS like dependency injection, scopes, watches, and expressions are also explained at a high level.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 97

AngularJS End to End

Building your First App


(basic concepts)
Setup: Template
<html ng-app='coolApp'>

<body>

<script src='angular.js'></script>
<script src='coolApp.js'></script>
</body>
</html>
Setup: JS

var myApp = angular.module('coolApp', []);


Principles

Boilerplate

D.R.Y. Structure Testability


Structure: Model-View-Controller
<div>
Observes Model
View
<span> <ul>
RAM (JS
<li> (DOM)
Objects)

Notifies Manages

Controller
(JS Classes)
Model:
{ "name": "Misko" }

View:
<p ng-controller='PersonController as person'>
Hi, {{person.model.name}}
</p>

Controller:

myApp.controller('PersonController', function () {
this.model = { name: 'Misko' };
});
Model:
{ "name": "Misko" }

View:
<p ng-controller='PersonController as person'>
Hi, {{person.model.name}}
</p>

Controller:

myApp.controller('PersonController', function (s) {


this.model = s.getPerson();
});
Feature: Data Binding
hello.js

this.greeting = 'Hola!';

hello.html

{{ greeter.greeting }} // 1-way
<input ng-model='greeter.greeting'> // 2-way
Note: Binding for initial page load
Markup fine except for first page

<p>{{someObj.something}}</p>

Use ng-cloak to avoid unstyled content on load

<p ng-cloak>{{someObj.something}}</p>

Attribute form also avoid unstyled content on load

<p ng-bind='someObj.something'></p>
Feature: Directives

<div ng-repeat='item in cart.items'>


<span ng-bind='item.name'></span>
<button ng-click='cart.delete($index)'>
Delete
</button>
</div>
Note: Directive validation

<div data-ng-repeat='item in cart.items'>


<span data-ng-bind='item.name'></span>
<button data-ng-click='cart.delete($index)'>
Delete
</button>
</div>
Feature: Dependency Injection
Definition

function MyFoo() { … };
module.service('foo', MyFoo);

Usage

function MyBar(foo) {
Foo instanceof MyFoo; // true!
}
Preferred usage

myApp.service('foo', function() {
...
});
Principle: Eliminate boilerplate

Dependency Injection

POJO Models

No DOM in most code paths


View Templates
Directives

Markup {{ }}

Form Validation

Filters
Filters
<p>{{ invoice.total | currency }}</p>
Filter example: Reverse
myApp.filter('reverse', function() {
return function(input) {
var out = '';
for (var i = 0; i < input.length; i++) {
out = input.charAt(i) + out;
}
return out;
}
});
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
$scope
You can request $scope in controllers

myApp.controller('GreetCtrl', function ($scope) {


$scope.greeter = { greeting: 'Misko'};
});

Use in template

<p ng-controller='GreetCtrl'>{{greeter.greeting}}</p>
$scope

Context for expression evaluation

Hierarchical, mirroring your DOM structure

Prototypal inheritance = global read, local write


$scope
$watch(expression, callback): Executes a callback
whenever a given expression changes
$apply() : synchronize data binding from outside
Angular's event loop
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


Expression Examples
person.name

shoppingCart.total()

cart.total() - user.discountRate
Talking to servers

$http: HTTP server communication


$resource: RESTful server communication
Notable other options:
● Restangular
● AngularFire
● BreezeJS
$http
this.someData = $http.get('/someUrl');
$http
$http.get('/someUrl').
success(function(data, status, headers, config) {
// called asynchronously
}).
error(function(data, status, headers, config) {
// called if an error occurs, also async
});
Promises
$http.post('/user/', user).then(
function() {
alert('Successfully created user!');
}, function() {
alert('Error creating user...');
}
);
Routes
Header
Left Nav

Content View
Routes
<ng-view> directive as content placeholder

$routeProvider to configure:
● Controller
● Template
● URL
Routes
myApp.config(function($routeProvider) {
$routeProvider.when('/inbox', {
templateUrl: 'inbox.html',
controller: 'InboxCtrl',
controllerAs: 'inbox'
});
});
Resources
Tools UI Components Libraries Books

Batarang Bootstrap
Learning Resources

docs.angularjs.org egghead.io thinkster.io pluralsight.com


/tutorial
Questions?
Internals of AngularJS
(How it all works)
Data Binding

Goal: Separate code from HTML


Data Binding
<div>

Model Drives <span> <ul>

<li>
<li>
<li>

<div>

Model Depends on <span> <ul>

<li>
<li>
<li>
Data Binding: Requirements
• Model is a Plain-Old-JavaScript-Object
• Detect value changes
• Easily describe value in the model
• Encapsulate DOM access
Scope

Goal: Provide context for expressions


Scope
User = function () {
this.fullName = 'Miško Hevery';
this.username = 'mhevery';
}
scope = {};
scope.user = new User();
{{user.fullName}}
{{user.username}}
Scope
{{name}}
<ul>
<li ng-repeat="name in names">
{{name}}
</li>
</ul>
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');
Scope
function inherit(parent) {
function C() {}
C.prototype = parent;
return new C();
}
parent = {};
child = inherit(parent);
expect(child.__proto__).toBe(parent);
Scope
{{name}}
<ul>

<li ng-repeat="name in names">


{{name}}
</li>

</ul>
Watchers

Goal: Notify of model changes


Watchers
{{name}}
scope.name = 'Miško Hevery';

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

Goal: Non-intrusive change detection


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

var lastValue;
function dirtyCheck() {
var value = scope.name;
if (lastValue != value)
reactionFn(value);
lastValue = value;
}
Digest Cycle
scope.$watch('count', function(value) {
alert(value);
});

scope.$watch('name', function(value) {
scope.count++;
});
Digest Cycle

Goal: Knowing when to digest


Digest Cycle
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
Digest Cycle: Sync vs Async
StackFrame

#3 asyncApi()
#2 yourApplicationBehavior()
#1 ng.$apply()
#0 nativeCode(event)
Expressions

Goal: Code of least surprise


Expressions
{{user.firstName}}

eval('with(scope){return
user.firstName;}');

if (scope.user) {
return scope.user.firstName;
}
Expressions
• eval() can not be the solution
• silent dereference
• executes in global context
• CSP
• Security
Expressions
• Let's think out of the box
• Let's implement JavaScript in JavaScript
• Full lexer and parser implies full control over:
• Syntax
• Semantics
Directive

Goal: Express intent in HTML


Directive
<ul>
<li ng-repeat="user in users">
{{user.name}}
</li>
</ul>
Directive
scope.$watch('name', function(value) {
element.text(value);
});

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

Goal: extend HTML syntax


(teach browser new tricks)
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
Dependency Injection

Goal: Get rid of setup code


Dependency Injection
function Door() {}
function House(door) {}
function App(house) {}

// implied
app = new App(new House(new Door)));
Dependency Injection

How do you know what to inject?


Dependency Injection
function Door() {}

function House(door) {}
House.$inject = ['door'];

function App(house) {}
App.$inject = ['house'];
Dependency Injection
describe('something', function() {
function test($rootScope){}
test.$inject = ['$rootScope'];
it('should ...', test);
});
Dependency Injection
function House(door) {}
House.$inject =
creazyRegExp(House.toString());
Dependency Injection
function Door(){}
function House(door) {}

injector = new Injector(...);


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

Add Caching, Modules and


some syntactic sugar and
you have full DI system
Routing

Goal: Preserve the web paradigm


Routing
• Deep linking
• Links work like links
• Support HTML5 pushstate
• URL rewriting
Routing
<a href="/chapter/{{id}}">

http://server.com/chapter/123
http://server.com/#!/chapter/123

• Server cooperation needed


REST

Goal: Easy server communication


REST
• Make common case simple
• Take advantage of data-binding
• Future / Promises
REST
Chapter = $resource('/chapter/:chapterId');

var chapters = Chapter.query();

<div ng-repeat="chapter in chapters">


{{chapter.name}}
</div>
Questions?
The New Stuff
(animations, track by, controller as, security,
error messages)
Brian Ford and Igor Minar
Animations in Angular

Animations are a natural extension


of CSS3 animations and
AngularJS directives
Animations in Angular

Angular automatically coordinates DOM


operations, so you can focus on the
visuals of the animation.
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; animation: 0.5s my_animation;
opacity: 0; }
}
@keyframes my_animation {
.item.ng-enter.ng-enter-active, from { opacity:1; }
.item.ng-move.ng-move-active { to { opacity:0; }
opacity: 1; }
}
Animation Hooks

http://docs.angularjs.org/guide/animations
Animation in Action
Example App: https://github.com/matsko/ngconf-animations-demo
Animation (& Touch) in Action
Example: Sidebar

● ngIf
● ngSwipeLeft/Right
Animation in Action
Example: Slideshow

● ngView
Animation in Action
Example: Notifications

● ngRepeat
Animation Best Practices
With great power comes great responsibility

● Be tasteful
○ use sparingly
● They should enhance UX
○ same functionality, but better affordances
● Keep them fast
○ http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/
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>
"Controller As"
Before:

<div ng-controller="UserController">
<p>{{name}}</p>
<div ng-if="someCondition">
<input ng-model="name">
</div>
</div>
"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>
Security Enhancements

● Template origin verification


● Expression sandbox hardening
● Better Content Security Policy support
● SCE
SCE (strict contextual auto-escaping)
<input ng-model="userHtml">

<div ng-bind-html="userHtml">
SCE (strict contextual auto-escaping)
var htmlSrc = '<div>...</div>';

var htmlWrapper = $sce.trustAsHtml(htmlSrc);

var htmlDst = $sce.getTrustedHtml(htmlWrapper);


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
minErr - Improved Error Messages
[$rootScope:infdig] http://...?p0=10&...
Questions?

You might also like