SlideShare a Scribd company logo
AngularJS training
Lauri Svan
lauri.svan@sc5.io @laurisvan
(original by kari.heikkinen@sc5.io)
Intro: About the Lecturer
● 15 year battle hardened veteran
● Head of Technology at SC5
● Helsinki Node.js co-founder
● In GitHub & Twitter
● “New school of engineering”
● Knows “why” & some “how” of
AngularJS
Intro: SC5
Yes, we’re hiring!
What is AngularJS
● Developed and maintained by Google
● Current version 1.5 (2.0 in Alpha)
● Good documentation and examples
● 3rd party libraries
● Insanely popular (see Bower, too)
● Easy to learn
● Get things done fast
● “Good enough”
Concepts
Two way data-binding
Dependency Injection (DI)
Application structure
Data driven development!
Recipe for an Angular Application
App Logic:
● 1 Module (the app)
● 1-N Templates for each view
● 1-N Controllers for each view
● 1 Router to toggle between UI states
● 1-N Directives for widgets
● 0-N Resources for each REST API
endpoints
● 0-N Services for inter-app comms &
storing app state
What else?
● Style sheets for app visuals
● Hybrid packaging (optional)
Modules
// Create module without dependencies
angular.module(‘myModule’, [ ] );
// Module with dependency
var app = angular.module(‘myApp’, [ ‘myModule’ ] );
// Get module and define controller
var module = angular.module(‘myModule’);
module.controller( ‘myController’, function($scope) {
$scope.title = ‘myController’;
});
// Declare application in HTML
<div ng-app=”myApp”>
// Declare application to body in javascript
angular.bootstrap( document.body, [‘myApp’] );
Template expressions
Angular template syntax uses double-curly brackets to
bind expression ‘{{ expression }}’.
<span>1+2={{ 1 + 2 }}</span>
{{ ‘Hello’ + ‘ World’ }}
{{ scopeVariable }}
{{ scopeFunction() }}
<img src=”{{ imageUrl }}”>
Controllers
● Controllers allow to interact with a View and Model.
● Is where to hold your presentation logic.
● Controller purpose is to drive Model and View
changes.
● New instance is created for each invocation
Controllers + $scope
Context where the model is stored so that controllers, directives and
expressions can access it.
$scope is a clever Object which is automated bridge between Javascript and
DOM that holds synchronized data.
var app = angular.module(‘myApp’);
app.controller(‘myCtrl’, function( $scope ) {
$scope.title = “MyTitle”;
});
app.controller(‘MySubCtrl’, function( $scope ) {
$scope.content = “MyData”;
});
<div ng-controller=”myCtrl”>
<h1>{{ title }}</h1>
<div ng-controller=”MySubCtrl”>
<p>{{content }}</p>
<span>ref: {{ title }}</span>
</div>
<div>{{content }}</div>
</div>
ControllerAs
New way in 1.3, similar as will be in 2.0
Easier to identify which scope is variable belongs to.
var app = angular.module(‘myApp’);
app.controller(‘myCtrl’, function() {
this.title = “MyTitle”;
});
app.controller(‘MySubCtrl’, function() {
this.content = “MyData”;
});
<div ng-controller=”myCtrl as mainCtrl”>
<h1>{{ mainCtrl.title }}</h1>
<div ng-controller=”MySubCtrl as subCtrl”>
<p>{{ subCtrl.content }}</p>
<span>ref: {{ mainCtrl.title }}</span>
</div>
<div>{{ subCtrl.content }}</div>
</div>
$scope.$watch
Way to react View change in the controller
app.controller(‘myCtrl’, function($scope) {
this.value = ‘Initial value’;
var _this = this;
$scope.$watch(
// return variable to watch (reference)
function() {
return _this.value;
},
// Handler function
function( newValue, oldValue ) {
console.log( oldValue, ‘->’, newValue );
}
);
});
app.controller(‘myCtrl’, function($scope) {
$scope.value = ‘Initial value’;
$scope.$watch(
‘value’,
function( newValue, oldValue ) {
console.log( oldValue, ‘->’, newValue );
}
);
});
W
ithout ControllerAs (1.2.x)
Services
● Use to hold data that persist application lifecycle, as
controllers are discarded when they are removed
from view.
● All services are singletons.
● Controllers access services via dependency injection.
● Three ways of creating services: service, factory, provider
Service
Creates service which will be invoked with ‘new’ to create
instance. (singleton instance)
app.service( ‘MyService’, function() {
this.greet = function() { alert(‘Hello!’); };
this.getText = function() { return ‘Hello!’; };
});
app.controller(‘myCtrl’, function(MyService) {
this.text = MyService.getText();
this.sayHello = function() {
MyService.greet();
}
});
var ServiceClass = function() {
this.color = ‘green’;
}
ServiceClass.prototype.setColor = function(color) {
this.color = color;
}
app.service( ‘MyService’, ServiceClass );
app.controller(‘MyController’, function(MyService) {
this.color = MyService.color;
this.onClick= function(color) {
MyService.setColor(color);
}
});
Factory
Register service by returning service instance object.
Can take advantage of closures.
app.factory( ‘MyService’, function() {
var greetText = “Hello”;
return {
greet: function() { alert(greetText); },
setText: function(text) { greetText = text; }
};
});
// Probably most common way to use factory
app.factory(‘Articles’, function( $resource, Settings ) {
return $resource( Settings.ApiHost + ‘/api/article’ );
}
app.controller(‘myCtrl’, function(MyService) {
this.text = MyService.getText();
this.sayHello = function() {
MyService.greet();
}
});
Providers
Only service definition that can be passed to config()
function.
Use to customize service on configuration phase.
app.provider( ‘MyService’, function() {
this.host = ‘/’;
this.$get = function( $resource ) {
return $resource( this.host + ‘/api/myservice’ );
};
});
app.config( function( MyServiceProvider ) {
if( window.location.host !== ‘example.com‘ )
MyServiceProvider.host = ‘example.com‘;
});
app.controller(‘myCtrl’, function(MyService) {
this.data = MyService.get( {id: 1234} );
});
Value & Constant
angular.module(‘myApp’).value( ‘Settings’, { host: ‘example.com’ } );
angular.module(‘myApp’).constant( ‘Config’, { host: ‘example.com’ } );
angular.module(‘myApp’).config( function(Config, MyServiceProvider ) {
MyServiceProvider.setApiHost( Config.host );
});
angular.module(‘myApp’).controller( ‘myCtrl’, function( Settings, $http ) {
var _this = this;
$http( Settings.host + ‘/api/data’ ).success( function(data) {
_this.data = data;
});
});
Filters
Filters are used for formatting data displayed to the
user.
Primarily used in expressions, but can be used in
controllers and services also.
{{ expression | filter1 | filter2 | ... }}
<span>{{ article.published | date:”yyyy-M-d” }}<span>
<span>{{ item.price | currency:”€” }}</span>
<label>{{ ‘ITEM_PRICE’ | translate }}</label>
<div ng-repeat=”person in persons | orderBy:’lastName’ | limitTo: 10”>{{ person.lastName}}</div>
// TIP: json filter is handy to check what object contains
<pre>{{ obj | json }}</pre>
Built-in filters
● currency - Format currency ( symbol, how many decimal numbers)
● number - To string, how many decimal numbers to use
● date - Format Date to string, use locale format as default
● json - Object to JSON string
● lowercase - Converts string to lowercase
● uppercase - Converts string to uppercase
● filter - select subset of array
● limitTo - creates new array with specified number of elements
● orderBy - Order array by the expression
Custom filter
app.filter( ‘translate’, function( LocalizationService ) {
return function( str ) {
return LocalizationService.getTranslation( str );
};
});
app.constant( ‘Settings’, { dateFormat: ‘d.M.yyyy’ } );
app.filter( ‘formatDate’, function( $filter, Settings ) {
var dateFilter = $filter.get(‘date’);
return function( date ) {
return dateFilter( date, Settings.dateFormat );
}
});
app.filter( ‘fullName’, function() {
return function( person ) { return person.firstName + ‘ ‘ + person.lastName; };
});
Directives
A Directive can be anything, it can either provide powerful logic to an
existing specific element, or be an element itself and provide an injected
template with powerful logic inside.
Directives are markers on a DOM element (such as an attribute, element
name, comment or CSS class) that tell AngularJS's HTML compiler to attach
a specified behavior to that DOM element or even transform the DOM
element and its children.
Angular comes with a set of built-in directives:
ng-model, ng-repeat, ng-show/ng-hide, ng-if, ng-click, ng-disabled, ng-
mouseover, ng-blur, ng-src/ng-href, ng-class, ng-switch, ng-bind, ng-view ….
Custom directives 1
Directives can match attribute name, tag name,
comments or class name. Or restricted only to match
some of them
<my-dir></my-dir>
<span my-dir="exp"></span>
<!-- directive: my-dir exp -->
<span class="my-dir: exp;"></span>
Directives can emulate Shadow DOM behaviour with
option transclude
<my-element>
Hi there!
</my-element>
Custom directives 2
app.controller(‘myCtrl, function() {
this.person = { firstName: ‘John’, lastName: ‘Doe’ };
});
app.directive(‘person’, function() {
return {
template: ‘{{person.lastName}}, {{person.firstName}}’
};
});
<div ng-controller=”myCtrl”>
<h1>Hello <person></person></h1>,
<p>...</p>
</div>
Custom directives 3
app.directive(‘article’, function() {
return {
restrict: ‘EA’,
scope: { article: ‘=article’ },
templateUrl: ‘article.html
};
});
app.controller(‘myCtrl’, function() {
this.article = {
title: ‘Headline’,
content: ‘Lore ipsum’,
published: 1234554543543,
author: ‘John Doe’
}
});
article.html:
<article>
<header>
<h1>{{article.title}}</h1>
<p>Posted by {{ article.author }}</p>
<p>{{ article.published | date: ‘d.M.yyyy’ }}</p>
</header>
<p>{{ article.content }}</p>
</article>
index.html:
<article=”myCtrl.article”></article>
<div article=”MyCtrl.article”></div>
Custom directives 4
app.directive(‘article’, function() {
return {
restrict: ‘E’,
scope: { data: ‘=data },
bindToController: true,
templateUrl: ‘article.html,
controlelrAs, ‘article’,
controller: function() {
this.addComment = function(msg) {
this.data.comments.push(msg);
this.data.$save();
}
}
};
});
<article>
<header>
<h1>{{article.data.title}}</h1>
</header>
<p>{{ article.data.content }}</p>
<div class=comments>
<ul>
<li ng-repeat=”comment in article.data.comments”>{{ comment }}</li>
</ul>
<input ng-model=”newComment”/>
<button ng-click=”article.addComment(newComment)”>Send</button>
</div>
</article>
Custom directive 5 (transclude)
app.directive(“hideable”, function() {
return {
replace: true,
transclude: true,
template: [
‘<div ng-init=”hide=false”>’,
’<button ng-click=”hide=!hide”>Show/Hide</button>’,
‘<div ng-transclude ng-hide=”hide”></div>’,
‘</div>’
].join(‘’)
};
});
<div>
<h1> {{ title }} </h1>
<hideable>
<h2>{{ subTitle }}</h2>
<p>{{ content }}</p>
</hideable>
</div>
<div>
<h1> {{ title }} </h1>
<div ng-init=”hidden=false”>
<button ng-click=”hidden=!hidden”>Show/Hide</button>
<div ng-hide=”hidden”>
<h2>{{ subTitle }}</h2>
<p>{{ content }}</p>
</div>
</div>
</div>
Directive configuration
priority: 0,
template: '<div></div>', // or templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
transclude: false,
restrict: 'A',
templateNamespace: 'html',
scope: false,
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
controllerAs: 'stringAlias',
bindToController: false,
require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { ... },
post: function postLink(scope, iElement, iAttrs, controller) { ... }
}
},
// or
// link: function postLink( ... ) { ... }
Forms
Form and controls provide validation services, so that
the user can be notified of invalid input.
This provides a better user experience, because the user
gets instant feedback on how to correct the error.
Forms
<form name=”myFrom” novalidate>
<label>Email:</label>
<input type=”email” name=”email” ng-model=”user.email” required />
<label>Password:</label>
<input type=”password” name=”password” ng-model=”user.password” required minlength=”8” />
<div ng-messages=”myForm.password.$error”>
<div ng-message=”required”>Password is required</div>
<div ng-message=”minlength”>Password is too short</div>
</div>
<button ng-disabled=”myForm.$invalid”>Submit</button>
</form>
Form CSS classes
● ng-valid: the model is valid
● ng-invalid: the model is invalid
● ng-valid-[key]: for each valid key added by $setValidity
● ng-invalid-[key]: for each invalid key added by $setValidity
● ng-pristine: the control hasn't been interacted with yet
● ng-dirty: the control has been interacted with
● ng-touched: the control has been blurred
● ng-untouched: the control hasn't been blurred
● ng-pending: any $asyncValidators are unfulfilled
Form CSS class example
<form name=”myFrom” novalidate>
<label>Email:</label>
<input
type=”email”
name=”email”
ng-model=”user.email”
required />
</form>
<style type="text/css">
form input.ng-invalid.ng-dirty {
outline-color: #FA787E;
}
</style>
Form validators
HTML5 input validators are built-in to Angular:
number, email, required, url, time, date, ..
Create own validators with directives:
<input name=”pwd”
type=”password
ng-model=”user.password”
required
minlength=”8”
validate-password-characters />
<div ng-messages=”myFrom.pwd.$error”>
<div ng-message=”required”>Password is required</div>
<div ng-message=”minlength”>Password is too short</div>
<div ng-message=”passwordCharacters”>Your password must contain a numeric, uppercase and ..
</div>
</div>
Custom validator
app.directive('validatePasswordCharacters', function() {
var REQUIRED_PATTERNS = [
/d+/, //numeric values
/[a-z]+/, //lowercase values
/[A-Z]+/, //uppercase values
/W+/, //special characters
/^S+$/ //no whitespace allowed
];
return {
require : 'ngModel',
link : function($scope, element, attrs, ngModel) {
ngModel.$validators.passwordCharacters = function(value) {
var status = true;
angular.forEach(REQUIRED_PATTERNS, function(pattern) {
status = status && pattern.test(value);
});
return status;
};
}
}
});
Async validator
angular.module(‘myApp’).directive(‘validateUsernameAvailable’, function($http) {
return {
require: ‘ngModel’,
link: function( scope, element, attr, ngModel ) {
ngModel.$asyncValidators.usernameAvailable = function(username) {
return $http.get(‘/api/username-exists?username=’ + username );
}
}
};
});
<input type=”text” name=”myUsername” validate-username-available />
<div ng-if="myForm.myUsername.$pending"> Checking Username… </div>
<div ng-if="myForm.myUsername.$error.usernameAvailable"> User name is in use </div>
<button ng-disabled=”!myForm.$valid”>Submit</button>
ngModelOptions
Validation and specially async validation may cause too
many calls for validation.
With ngModelOptions you can control when ngModel is
updated and validators are executed.
// Update when leaving input element
<input ng-model=”value” ng-model-options=”{ updateOn:’blur’ }” required />
// Update only when no changes in 500ms or immediately when leaving element
<input ng-model=”username” ng-model-options=”{ debounce: { default: 500, blur: 0 } }”
required validate-username-available />
Events
Angular scope have built-in event framework.
● $on - listen to event
● $emit - send event to upwards (self and parent
scopes)
● $broadcast - send event to downwards (self / child
scopes)
<div ng-controller="EventCtrl as parentCtrl" ng-scope>
<div ng-controller="EventCtrl as childCtrl1" ng-scope>
<div ng-controller="EventCtrl as subChildCtrl" ng-scope></div>
</div>
<div ng-controller="EventCtrl as childCtrl2" ng-scope>
</div>
</div>
$broadcast $send
Angular extension modules
● ngRoute - Routing and deeplinking
● ngResource - RESTful services
● ngAnimate - Support for JS, CSS transitions and
animations hooks
● ngSanitize - Bind HTML content safe way
● ngTouch - Touch events
● ngMessages - Enhanced support to show messages
ngRoute
To create routing for your Angular application include
ngRoute module and defined routes in config()-function.
angular.module(´myApp´, [´ngRoute´]).config(
function( $routeProvider, $locationProvider ) {
$routeProvider
.when('/', {
templateUrl: 'main.html',
controller: ´mainController´
}).
.when('/page1', {
templateUrl: page1.html',
controller: ´page1Controller´
}).
.otherwise({ redirectTo: ´/´ });
$locationProvider.html5Mode(true);
});
index.html:
<body>
<div ng-view> Route content will be here </div>
main.html:
<h1>main page</h1>
<a href=”/page”>goto to sub page</a>
page.html:
<h1>Page1 </h1>
<a href=”/”>back to main page</a>
ngRoute - resolve content
angular.module('myApp').config( function($routeProvider) {
$routeProvider.
when("/article/:id", {
templateUrl: 'article.html',
controller: 'ArticleCtrl',
controllerAs: ‘articleCtrl’,
resolve: {
article: function($resource, $route, $q, $location) {
var Article = $resource(‘/api/article/:id’);
var request = Article.get({id: $route.current.params.id});
request.$promise.catch( function() {
$location.path(‘/notfound’);
$location.replace();
});
return request.$promise;
}
}
});
});
angular.module(‘myApp’)
.controller( ‘articleCtrl’,
function( article ) {
this.data = article;
});
ngResource
Factory service which creates a resource object that lets
you to interact RESTful API.
Makes data handling object oriented.
var User = $resource(
‘/api/user/:id’,
{ id: ‘@_id’ },
{
update: { method: ‘PUT’ }
});
var person = new User({
firstName: ‘John’,
lastName:’doe’
});
person.$save();
person.lastName = ‘Doe’;
person.$update();
var person = new User({
firstName: ‘John’,
lastName:’doe’
});
person.$save(); // POST: ‘/api/user’
person.lastName = ‘Doe’;
person.$update(); // PUT: ‘/api/user/1’
// GET: ’/api/user?firstName=John’
var users = User.query({ firstName: ‘John });
var john = User.get({ id: 1234 }, function() {
john.lastLogin = new Date();
john.$update();
});
ngResource
Default configuration:
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
ngResource
var Article = $resource(‘/api/article/:id’, { id: ‘@_id’ }, {
recent: {
method: ‘GET’,
isArray: true,
cache: true, // use http cache for method
params: { limit: 10, latest: true }
}
});
// GET: /api/article?limit=10&latest=true&type=news
var latestArticles = Article.$latest( { type: ‘news’ } );
latestArticles.$promise
.success( function() {
// articles loaded
})
.catch( function() {
// request failed
});
ngAnimate
Adds animation hooks for common directives such as
ngRepeat, ngView and ngShow.
Also pays attention to CSS class changes with ngClass by
triggering add and remove hooks.
When change is triggered it places state CSS class, like
ng-hide, and end state ng-hide-active. And after
animation is ended it removes those classes
ngShow animate
<button ng-click=”hide=!hide”>Show/hide</button>
<div class=”animate” ng-show=”hide”>
Shown/hide with animation
</div>
<style>
.animate { opacity: 1; }
.animate.ng-hide { opacity: 0; }
.animate.ng-hide-add,
.animate.ng-hide-remove {
-webkit-transition: 1s linear all;
transition: 1s linear all;
}
</style>
JS animation with jQuery
angular.module('myApp',['ngAnimate']).animation('.animate', function() {
return {
beforeAddClass: function(element, className, done) {
if( className === 'ng-hide' )
element.animate({ opacity: 0 }, 500, done );
else
done();
},
removeClass: function(element, className, done) {
if( className === 'ng-hide' )
element.css({ opacity: 0 }).animate({ opacity: 1}, 500, done );
else
done();
}
}
})
Testing
AngularJS is designed that applications are testable.
Dependency Injection makes testing easier, by allowing
inject mock instead of real module.
Unit testing with Karma
my-ctrl.js:
angular.module('myApp',[])
.controller('myCtrl', function( $http ) {
var _this = this;
$http.get('/api/data').success(function(data) {
_this.data = data;
});
this.isOk = function() {
return this.data && this.data.ok;
}
});
my-ctrl.spec.js:
describe('controller:myCtrl', function() {
beforeEach( module('myApp') );
it('should fetch data from server and return ok',
inject(function($controller, $httpBackend) {
$httpBackend
.when('GET', '/api/data')
.respond({ ok: true });
$httpBackend.expectGET('/api/data');
var ctrl = $controller( 'myCtrl' );
expect(ctrl.isOk()).toBe(false);
$httpBackend.flush();
expect(ctrl.isOk()).toBe(true);
})
);
});
Dependency Injection in testing
it('should fetch data from server and return ok', inject(function($controller) {
var ctrlCB;
var myHttpMock = {
get: function() {
return {
success: function(cb) { ctrlCB= cb; }
};
}
}
var ctrl = $controller( 'myCtrl', { $http: myHttpMock } );
expect(ctrlCB).not.toBe(undefined);
cb( { ok: true } );
expect(ctrl.isOk()).toBe( true );
}));
End-to-end testing with protractor
describe('password view', function() {
it('should show error when too short input', function() {
browser.get('http://localhost:63342/angular-training/protractor/index.html');
element(by.model('user.password')).sendKeys('test');
var messages = element(by.id('password.error'));
expect(messages.getText()).toContain('short');
element(by.model('user.password')).sendKeys('test12345ABC-');
element(by.buttonText(‘save’)).click();
});
});
Best practices
● Design UI/HTML first!
Create HTML first and then just add functionality with
Angular. Style guide + UI mock-ups
● Avoid using $scope directly
By eliminating usage of $scope, code is closer to 2.0
style
● Avoid using ng-controller in HTML
Use through route or directives, do not add them
directly.
● Testing is easy!
Write tests for your code / site
Best practices
● If repeating elements in HTML, create directive for them
● Create services and use $resource to access server APIs
● Do not format data in the controllers, which will be displayed in the
view, instead use filter. Example, localisation, date/time, currency, etc.
Create filters that do it for you, and you can then modify those filters
and reflect changes to whole site.
● Avoid long lists which contains lots of bind data, that can cause
performance issues. Use paging to limit elements, if data changes in
page, otherwise use one-time binding (Angular 1.3), or libraries like
‘bindonce’ for Angular 1.2
● If you are binding without dot, you are probably doing something
wrong. {{ name }} = BAD, {{ user.name }} = GOOD
● Keep code structured
Caveats
● 2000 watches is considered as saturation point, after that page
rendering may seem slow
● Use directive isolated scope only when needed. Specially with
transclude, it can cause problems not to be able to access variables
● Namespace
Modules does not add namespace for functions. Plan function naming
(controller/service/directive/filter)
● Dependency Injection and javascript minify
DI breaks when minified. Declare in array syntax or use
ngAnnote/ngMin
● When using 3rd party libraries etc, remember to call $apply to get
changes render to page
Tools & Utilities for AngularJS
Boilerplates
https://github.com/SC5/gulp-bobrsass-boilerplate/tree/angularjs
https://github.com/DaftMonk/generator-angular-fullstack
Testing:
http://angular.github.io/protractor/#/
http://karma-runner.github.io/0.12/index.html
http://www.ng-newsletter.com/advent2013/#!/day/19
Build and minification:
https://github.com/olov/ng-annotate
More about AngularJS
Community in Helsinki capital area
https://www.facebook.com/groups/helsinkijs/
http://frontend.fi/
AngularJS Primer
https://www.airpair.com/angularjs/posts/angularjs-tutorial
https://thinkster.io/angulartutorial/a-better-way-to-learn-angularjs/
http://lostechies.com/gabrielschenker/2013/12/05/angularjspart-1/
Blogs that have good information about AngularJS:
http://www.yearofmoo.com/
http://www.jvandemo.com/
Good reads:
http://sc5.io/posts/how-to-implement-loaders-for-an-angularjs-app
http://teropa.info/blog/2014/11/01/why-i-think-angular-2-will-still-be-angular.html
Conclusion and discussion
What did we learn?
Discussion about AngularJS
Test setup
● Install Node.js for test server
http://nodejs.org/download/
● Download and extract training examples
https://docs.google.com/a/sc5.io/uc?
authuser=0&id=0B_18Pna_ughFNWVZaUV1amV6bjA&export=download
● Go to exercises folder and execute commands
> npm install
> npm start
● Open local web server with browser
http://localhost:3000/

More Related Content

What's hot

Opinionated AngularJS
Opinionated AngularJSOpinionated AngularJS
Opinionated AngularJS
prabhutech
 
Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30) Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30)
Paco de la Cruz
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
Michele Orselli
 
Durable functions
Durable functionsDurable functions
Durable functions
명신 김
 
Implementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconfImplementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconf
Michele Orselli
 
Implementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile AppsImplementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile Apps
Michele Orselli
 
"Inside The AngularJS Directive Compiler" by Tero Parviainen
"Inside The AngularJS Directive Compiler" by Tero Parviainen"Inside The AngularJS Directive Compiler" by Tero Parviainen
"Inside The AngularJS Directive Compiler" by Tero Parviainen
Fwdays
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.AngularEvan Schultz
 
Introduction to Angular js
Introduction to Angular jsIntroduction to Angular js
Introduction to Angular jsMustafa Gamal
 
Angular 2 KTS
Angular 2 KTSAngular 2 KTS
Angular 2 KTS
John Vall
 
Solid angular
Solid angularSolid angular
Solid angular
Nir Kaufman
 
The battle of Protractor and Cypress - RunIT Conference 2019
The battle of Protractor and Cypress - RunIT Conference 2019The battle of Protractor and Cypress - RunIT Conference 2019
The battle of Protractor and Cypress - RunIT Conference 2019
Ludmila Nesvitiy
 
Angular 2 introduction
Angular 2 introductionAngular 2 introduction
Angular 2 introduction
Christoffer Noring
 
Evan Schultz - Angular Summit - 2016
Evan Schultz - Angular Summit - 2016Evan Schultz - Angular Summit - 2016
Evan Schultz - Angular Summit - 2016Evan Schultz
 
Angular custom directives
Angular custom directivesAngular custom directives
Angular custom directivesAlexe Bogdan
 
AngularJS Basics with Example
AngularJS Basics with ExampleAngularJS Basics with Example
AngularJS Basics with Example
Sergey Bolshchikov
 
Gwt and Xtend
Gwt and XtendGwt and Xtend
Gwt and Xtend
Sven Efftinge
 
Building Android apps with Parse
Building Android apps with ParseBuilding Android apps with Parse
Building Android apps with Parse
DroidConTLV
 
Auto-GWT : Better GWT Programming with Xtend
Auto-GWT : Better GWT Programming with XtendAuto-GWT : Better GWT Programming with Xtend
Auto-GWT : Better GWT Programming with Xtend
Sven Efftinge
 
Testowanie JavaScript
Testowanie JavaScriptTestowanie JavaScript
Testowanie JavaScript
Tomasz Bak
 

What's hot (20)

Opinionated AngularJS
Opinionated AngularJSOpinionated AngularJS
Opinionated AngularJS
 
Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30) Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30)
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
 
Durable functions
Durable functionsDurable functions
Durable functions
 
Implementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconfImplementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconf
 
Implementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile AppsImplementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile Apps
 
"Inside The AngularJS Directive Compiler" by Tero Parviainen
"Inside The AngularJS Directive Compiler" by Tero Parviainen"Inside The AngularJS Directive Compiler" by Tero Parviainen
"Inside The AngularJS Directive Compiler" by Tero Parviainen
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.Angular
 
Introduction to Angular js
Introduction to Angular jsIntroduction to Angular js
Introduction to Angular js
 
Angular 2 KTS
Angular 2 KTSAngular 2 KTS
Angular 2 KTS
 
Solid angular
Solid angularSolid angular
Solid angular
 
The battle of Protractor and Cypress - RunIT Conference 2019
The battle of Protractor and Cypress - RunIT Conference 2019The battle of Protractor and Cypress - RunIT Conference 2019
The battle of Protractor and Cypress - RunIT Conference 2019
 
Angular 2 introduction
Angular 2 introductionAngular 2 introduction
Angular 2 introduction
 
Evan Schultz - Angular Summit - 2016
Evan Schultz - Angular Summit - 2016Evan Schultz - Angular Summit - 2016
Evan Schultz - Angular Summit - 2016
 
Angular custom directives
Angular custom directivesAngular custom directives
Angular custom directives
 
AngularJS Basics with Example
AngularJS Basics with ExampleAngularJS Basics with Example
AngularJS Basics with Example
 
Gwt and Xtend
Gwt and XtendGwt and Xtend
Gwt and Xtend
 
Building Android apps with Parse
Building Android apps with ParseBuilding Android apps with Parse
Building Android apps with Parse
 
Auto-GWT : Better GWT Programming with Xtend
Auto-GWT : Better GWT Programming with XtendAuto-GWT : Better GWT Programming with Xtend
Auto-GWT : Better GWT Programming with Xtend
 
Testowanie JavaScript
Testowanie JavaScriptTestowanie JavaScript
Testowanie JavaScript
 

Viewers also liked

Machine Learning Using Cloud Services
Machine Learning Using Cloud ServicesMachine Learning Using Cloud Services
Machine Learning Using Cloud Services
SC5.io
 
AngularJS
AngularJSAngularJS
AngularJS
Yogesh L
 
Securing the client side web
Securing the client side webSecuring the client side web
Securing the client side web
SC5.io
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile Services
Rainer Stropek
 
Angular js-crash-course
Angular js-crash-courseAngular js-crash-course
Angular js-crash-course
Keith Bloomfield
 
AngularJS Best Practices
AngularJS Best PracticesAngularJS Best Practices
AngularJS Best Practices
Betclic Everest Group Tech Team
 
Angular js best practice
Angular js best practiceAngular js best practice
Angular js best practice
Matteo Scandolo
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
Eyal Vardi
 
AngularJS application architecture
AngularJS application architectureAngularJS application architecture
AngularJS application architecture
Gabriele Falace
 

Viewers also liked (9)

Machine Learning Using Cloud Services
Machine Learning Using Cloud ServicesMachine Learning Using Cloud Services
Machine Learning Using Cloud Services
 
AngularJS
AngularJSAngularJS
AngularJS
 
Securing the client side web
Securing the client side webSecuring the client side web
Securing the client side web
 
AngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile ServicesAngularJS with TypeScript and Windows Azure Mobile Services
AngularJS with TypeScript and Windows Azure Mobile Services
 
Angular js-crash-course
Angular js-crash-courseAngular js-crash-course
Angular js-crash-course
 
AngularJS Best Practices
AngularJS Best PracticesAngularJS Best Practices
AngularJS Best Practices
 
Angular js best practice
Angular js best practiceAngular js best practice
Angular js best practice
 
AngularJS Architecture
AngularJS ArchitectureAngularJS Architecture
AngularJS Architecture
 
AngularJS application architecture
AngularJS application architectureAngularJS application architecture
AngularJS application architecture
 

Similar to Angular.js Primer in Aalto University

AngularJs-training
AngularJs-trainingAngularJs-training
AngularJs-training
Pratchaya Suputsopon
 
AngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
AngularJs Superheroic JavaScript MVW Framework Services by Miracle StudiosAngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
AngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
Learnimtactics
 
MEAN - Notes from the field (Full-Stack Development with Javascript)
MEAN - Notes from the field (Full-Stack Development with Javascript)MEAN - Notes from the field (Full-Stack Development with Javascript)
MEAN - Notes from the field (Full-Stack Development with Javascript)
Chris Clarke
 
Angular Presentation
Angular PresentationAngular Presentation
Angular PresentationAdam Moore
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJS
Wei Ru
 
Angular workshop - Full Development Guide
Angular workshop - Full Development GuideAngular workshop - Full Development Guide
Angular workshop - Full Development Guide
Nitin Giri
 
AngularJS Workshop
AngularJS WorkshopAngularJS Workshop
AngularJS Workshop
Gianluca Cacace
 
AngularJS Basic Training
AngularJS Basic TrainingAngularJS Basic Training
AngularJS Basic Training
Cornel Stefanache
 
Angular js
Angular jsAngular js
Angular js
Baldeep Sohal
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
Keith Bloomfield
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications
Juliana Lucena
 
Angular js
Angular jsAngular js
Angular js
ParmarAnisha
 
Custom AngularJS Directives
Custom AngularJS DirectivesCustom AngularJS Directives
Custom AngularJS Directives
yprodev
 
AngularJS Custom Directives
AngularJS Custom DirectivesAngularJS Custom Directives
AngularJS Custom Directives
yprodev
 
AngularJS Deep Dives (NYC GDG Apr 2013)
AngularJS Deep Dives (NYC GDG Apr 2013)AngularJS Deep Dives (NYC GDG Apr 2013)
AngularJS Deep Dives (NYC GDG Apr 2013)
Nitya Narasimhan
 
angularJs Workshop
angularJs WorkshopangularJs Workshop
angularJs Workshop
Ran Wahle
 
AngularJs Workshop SDP December 28th 2014
AngularJs Workshop SDP December 28th 2014AngularJs Workshop SDP December 28th 2014
AngularJs Workshop SDP December 28th 2014
Ran Wahle
 
AngularJS Basics
AngularJS BasicsAngularJS Basics
AngularJS Basics
Ravi Mone
 
Modular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJSModular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJS
Gunnar Hillert
 

Similar to Angular.js Primer in Aalto University (20)

AngularJs-training
AngularJs-trainingAngularJs-training
AngularJs-training
 
Angular js
Angular jsAngular js
Angular js
 
AngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
AngularJs Superheroic JavaScript MVW Framework Services by Miracle StudiosAngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
AngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
 
MEAN - Notes from the field (Full-Stack Development with Javascript)
MEAN - Notes from the field (Full-Stack Development with Javascript)MEAN - Notes from the field (Full-Stack Development with Javascript)
MEAN - Notes from the field (Full-Stack Development with Javascript)
 
Angular Presentation
Angular PresentationAngular Presentation
Angular Presentation
 
Practical AngularJS
Practical AngularJSPractical AngularJS
Practical AngularJS
 
Angular workshop - Full Development Guide
Angular workshop - Full Development GuideAngular workshop - Full Development Guide
Angular workshop - Full Development Guide
 
AngularJS Workshop
AngularJS WorkshopAngularJS Workshop
AngularJS Workshop
 
AngularJS Basic Training
AngularJS Basic TrainingAngularJS Basic Training
AngularJS Basic Training
 
Angular js
Angular jsAngular js
Angular js
 
AngularJs Crash Course
AngularJs Crash CourseAngularJs Crash Course
AngularJs Crash Course
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications
 
Angular js
Angular jsAngular js
Angular js
 
Custom AngularJS Directives
Custom AngularJS DirectivesCustom AngularJS Directives
Custom AngularJS Directives
 
AngularJS Custom Directives
AngularJS Custom DirectivesAngularJS Custom Directives
AngularJS Custom Directives
 
AngularJS Deep Dives (NYC GDG Apr 2013)
AngularJS Deep Dives (NYC GDG Apr 2013)AngularJS Deep Dives (NYC GDG Apr 2013)
AngularJS Deep Dives (NYC GDG Apr 2013)
 
angularJs Workshop
angularJs WorkshopangularJs Workshop
angularJs Workshop
 
AngularJs Workshop SDP December 28th 2014
AngularJs Workshop SDP December 28th 2014AngularJs Workshop SDP December 28th 2014
AngularJs Workshop SDP December 28th 2014
 
AngularJS Basics
AngularJS BasicsAngularJS Basics
AngularJS Basics
 
Modular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJSModular Test-driven SPAs with Spring and AngularJS
Modular Test-driven SPAs with Spring and AngularJS
 

More from SC5.io

AWS Machine Learning & Google Cloud Machine Learning
AWS Machine Learning & Google Cloud Machine LearningAWS Machine Learning & Google Cloud Machine Learning
AWS Machine Learning & Google Cloud Machine Learning
SC5.io
 
Transfer learning with Custom Vision
Transfer learning with Custom VisionTransfer learning with Custom Vision
Transfer learning with Custom Vision
SC5.io
 
Practical AI for Business: Bandit Algorithms
Practical AI for Business: Bandit AlgorithmsPractical AI for Business: Bandit Algorithms
Practical AI for Business: Bandit Algorithms
SC5.io
 
Decision trees & random forests
Decision trees & random forestsDecision trees & random forests
Decision trees & random forests
SC5.io
 
Bandit Algorithms
Bandit AlgorithmsBandit Algorithms
Bandit Algorithms
SC5.io
 
Miten design-muutosjohtaminen hyödyttää yrityksiä?
Miten design-muutosjohtaminen hyödyttää yrityksiä?Miten design-muutosjohtaminen hyödyttää yrityksiä?
Miten design-muutosjohtaminen hyödyttää yrityksiä?
SC5.io
 
Engineering HTML5 Applications for Better Performance
Engineering HTML5 Applications for Better PerformanceEngineering HTML5 Applications for Better Performance
Engineering HTML5 Applications for Better Performance
SC5.io
 
2013 10-02-backbone-robots-aarhus
2013 10-02-backbone-robots-aarhus2013 10-02-backbone-robots-aarhus
2013 10-02-backbone-robots-aarhus
SC5.io
 
2013 10-02-html5-performance-aarhus
2013 10-02-html5-performance-aarhus2013 10-02-html5-performance-aarhus
2013 10-02-html5-performance-aarhus
SC5.io
 
2013 04-02-server-side-backbone
2013 04-02-server-side-backbone2013 04-02-server-side-backbone
2013 04-02-server-side-backbone
SC5.io
 
Building single page applications
Building single page applicationsBuilding single page applications
Building single page applications
SC5.io
 

More from SC5.io (11)

AWS Machine Learning & Google Cloud Machine Learning
AWS Machine Learning & Google Cloud Machine LearningAWS Machine Learning & Google Cloud Machine Learning
AWS Machine Learning & Google Cloud Machine Learning
 
Transfer learning with Custom Vision
Transfer learning with Custom VisionTransfer learning with Custom Vision
Transfer learning with Custom Vision
 
Practical AI for Business: Bandit Algorithms
Practical AI for Business: Bandit AlgorithmsPractical AI for Business: Bandit Algorithms
Practical AI for Business: Bandit Algorithms
 
Decision trees & random forests
Decision trees & random forestsDecision trees & random forests
Decision trees & random forests
 
Bandit Algorithms
Bandit AlgorithmsBandit Algorithms
Bandit Algorithms
 
Miten design-muutosjohtaminen hyödyttää yrityksiä?
Miten design-muutosjohtaminen hyödyttää yrityksiä?Miten design-muutosjohtaminen hyödyttää yrityksiä?
Miten design-muutosjohtaminen hyödyttää yrityksiä?
 
Engineering HTML5 Applications for Better Performance
Engineering HTML5 Applications for Better PerformanceEngineering HTML5 Applications for Better Performance
Engineering HTML5 Applications for Better Performance
 
2013 10-02-backbone-robots-aarhus
2013 10-02-backbone-robots-aarhus2013 10-02-backbone-robots-aarhus
2013 10-02-backbone-robots-aarhus
 
2013 10-02-html5-performance-aarhus
2013 10-02-html5-performance-aarhus2013 10-02-html5-performance-aarhus
2013 10-02-html5-performance-aarhus
 
2013 04-02-server-side-backbone
2013 04-02-server-side-backbone2013 04-02-server-side-backbone
2013 04-02-server-side-backbone
 
Building single page applications
Building single page applicationsBuilding single page applications
Building single page applications
 

Recently uploaded

原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
3ipehhoa
 
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shopHistory+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
laozhuseo02
 
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
3ipehhoa
 
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and GuidelinesMulti-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Sanjeev Rampal
 
test test test test testtest test testtest test testtest test testtest test ...
test test  test test testtest test testtest test testtest test testtest test ...test test  test test testtest test testtest test testtest test testtest test ...
test test test test testtest test testtest test testtest test testtest test ...
Arif0071
 
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
3ipehhoa
 
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptxLiving-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
TristanJasperRamos
 
Output determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CCOutput determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CC
ShahulHameed54211
 
1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...
JeyaPerumal1
 
ER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAEER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAE
Himani415946
 
How to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptxHow to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptx
Gal Baras
 
guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...
Rogerio Filho
 
The+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptxThe+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptx
laozhuseo02
 
BASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptxBASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptx
natyesu
 
Latest trends in computer networking.pptx
Latest trends in computer networking.pptxLatest trends in computer networking.pptx
Latest trends in computer networking.pptx
JungkooksNonexistent
 
This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!
nirahealhty
 

Recently uploaded (16)

原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
原版仿制(uob毕业证书)英国伯明翰大学毕业证本科学历证书原版一模一样
 
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shopHistory+of+E-commerce+Development+in+China-www.cfye-commerce.shop
History+of+E-commerce+Development+in+China-www.cfye-commerce.shop
 
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
1比1复刻(bath毕业证书)英国巴斯大学毕业证学位证原版一模一样
 
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and GuidelinesMulti-cluster Kubernetes Networking- Patterns, Projects and Guidelines
Multi-cluster Kubernetes Networking- Patterns, Projects and Guidelines
 
test test test test testtest test testtest test testtest test testtest test ...
test test  test test testtest test testtest test testtest test testtest test ...test test  test test testtest test testtest test testtest test testtest test ...
test test test test testtest test testtest test testtest test testtest test ...
 
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
急速办(bedfordhire毕业证书)英国贝德福特大学毕业证成绩单原版一模一样
 
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptxLiving-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
Living-in-IT-era-Module-7-Imaging-and-Design-for-Social-Impact.pptx
 
Output determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CCOutput determination SAP S4 HANA SAP SD CC
Output determination SAP S4 HANA SAP SD CC
 
1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...1.Wireless Communication System_Wireless communication is a broad term that i...
1.Wireless Communication System_Wireless communication is a broad term that i...
 
ER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAEER(Entity Relationship) Diagram for online shopping - TAE
ER(Entity Relationship) Diagram for online shopping - TAE
 
How to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptxHow to Use Contact Form 7 Like a Pro.pptx
How to Use Contact Form 7 Like a Pro.pptx
 
guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...guildmasters guide to ravnica Dungeons & Dragons 5...
guildmasters guide to ravnica Dungeons & Dragons 5...
 
The+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptxThe+Prospects+of+E-Commerce+in+China.pptx
The+Prospects+of+E-Commerce+in+China.pptx
 
BASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptxBASIC C++ lecture NOTE C++ lecture 3.pptx
BASIC C++ lecture NOTE C++ lecture 3.pptx
 
Latest trends in computer networking.pptx
Latest trends in computer networking.pptxLatest trends in computer networking.pptx
Latest trends in computer networking.pptx
 
This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!This 7-second Brain Wave Ritual Attracts Money To You.!
This 7-second Brain Wave Ritual Attracts Money To You.!
 

Angular.js Primer in Aalto University

  • 1. AngularJS training Lauri Svan lauri.svan@sc5.io @laurisvan (original by kari.heikkinen@sc5.io)
  • 2. Intro: About the Lecturer ● 15 year battle hardened veteran ● Head of Technology at SC5 ● Helsinki Node.js co-founder ● In GitHub & Twitter ● “New school of engineering” ● Knows “why” & some “how” of AngularJS
  • 4. What is AngularJS ● Developed and maintained by Google ● Current version 1.5 (2.0 in Alpha) ● Good documentation and examples ● 3rd party libraries ● Insanely popular (see Bower, too) ● Easy to learn ● Get things done fast ● “Good enough”
  • 5. Concepts Two way data-binding Dependency Injection (DI) Application structure Data driven development!
  • 6. Recipe for an Angular Application App Logic: ● 1 Module (the app) ● 1-N Templates for each view ● 1-N Controllers for each view ● 1 Router to toggle between UI states ● 1-N Directives for widgets ● 0-N Resources for each REST API endpoints ● 0-N Services for inter-app comms & storing app state What else? ● Style sheets for app visuals ● Hybrid packaging (optional)
  • 7. Modules // Create module without dependencies angular.module(‘myModule’, [ ] ); // Module with dependency var app = angular.module(‘myApp’, [ ‘myModule’ ] ); // Get module and define controller var module = angular.module(‘myModule’); module.controller( ‘myController’, function($scope) { $scope.title = ‘myController’; }); // Declare application in HTML <div ng-app=”myApp”> // Declare application to body in javascript angular.bootstrap( document.body, [‘myApp’] );
  • 8. Template expressions Angular template syntax uses double-curly brackets to bind expression ‘{{ expression }}’. <span>1+2={{ 1 + 2 }}</span> {{ ‘Hello’ + ‘ World’ }} {{ scopeVariable }} {{ scopeFunction() }} <img src=”{{ imageUrl }}”>
  • 9. Controllers ● Controllers allow to interact with a View and Model. ● Is where to hold your presentation logic. ● Controller purpose is to drive Model and View changes. ● New instance is created for each invocation
  • 10. Controllers + $scope Context where the model is stored so that controllers, directives and expressions can access it. $scope is a clever Object which is automated bridge between Javascript and DOM that holds synchronized data. var app = angular.module(‘myApp’); app.controller(‘myCtrl’, function( $scope ) { $scope.title = “MyTitle”; }); app.controller(‘MySubCtrl’, function( $scope ) { $scope.content = “MyData”; }); <div ng-controller=”myCtrl”> <h1>{{ title }}</h1> <div ng-controller=”MySubCtrl”> <p>{{content }}</p> <span>ref: {{ title }}</span> </div> <div>{{content }}</div> </div>
  • 11. ControllerAs New way in 1.3, similar as will be in 2.0 Easier to identify which scope is variable belongs to. var app = angular.module(‘myApp’); app.controller(‘myCtrl’, function() { this.title = “MyTitle”; }); app.controller(‘MySubCtrl’, function() { this.content = “MyData”; }); <div ng-controller=”myCtrl as mainCtrl”> <h1>{{ mainCtrl.title }}</h1> <div ng-controller=”MySubCtrl as subCtrl”> <p>{{ subCtrl.content }}</p> <span>ref: {{ mainCtrl.title }}</span> </div> <div>{{ subCtrl.content }}</div> </div>
  • 12. $scope.$watch Way to react View change in the controller app.controller(‘myCtrl’, function($scope) { this.value = ‘Initial value’; var _this = this; $scope.$watch( // return variable to watch (reference) function() { return _this.value; }, // Handler function function( newValue, oldValue ) { console.log( oldValue, ‘->’, newValue ); } ); }); app.controller(‘myCtrl’, function($scope) { $scope.value = ‘Initial value’; $scope.$watch( ‘value’, function( newValue, oldValue ) { console.log( oldValue, ‘->’, newValue ); } ); }); W ithout ControllerAs (1.2.x)
  • 13. Services ● Use to hold data that persist application lifecycle, as controllers are discarded when they are removed from view. ● All services are singletons. ● Controllers access services via dependency injection. ● Three ways of creating services: service, factory, provider
  • 14. Service Creates service which will be invoked with ‘new’ to create instance. (singleton instance) app.service( ‘MyService’, function() { this.greet = function() { alert(‘Hello!’); }; this.getText = function() { return ‘Hello!’; }; }); app.controller(‘myCtrl’, function(MyService) { this.text = MyService.getText(); this.sayHello = function() { MyService.greet(); } }); var ServiceClass = function() { this.color = ‘green’; } ServiceClass.prototype.setColor = function(color) { this.color = color; } app.service( ‘MyService’, ServiceClass ); app.controller(‘MyController’, function(MyService) { this.color = MyService.color; this.onClick= function(color) { MyService.setColor(color); } });
  • 15. Factory Register service by returning service instance object. Can take advantage of closures. app.factory( ‘MyService’, function() { var greetText = “Hello”; return { greet: function() { alert(greetText); }, setText: function(text) { greetText = text; } }; }); // Probably most common way to use factory app.factory(‘Articles’, function( $resource, Settings ) { return $resource( Settings.ApiHost + ‘/api/article’ ); } app.controller(‘myCtrl’, function(MyService) { this.text = MyService.getText(); this.sayHello = function() { MyService.greet(); } });
  • 16. Providers Only service definition that can be passed to config() function. Use to customize service on configuration phase. app.provider( ‘MyService’, function() { this.host = ‘/’; this.$get = function( $resource ) { return $resource( this.host + ‘/api/myservice’ ); }; }); app.config( function( MyServiceProvider ) { if( window.location.host !== ‘example.com‘ ) MyServiceProvider.host = ‘example.com‘; }); app.controller(‘myCtrl’, function(MyService) { this.data = MyService.get( {id: 1234} ); });
  • 17. Value & Constant angular.module(‘myApp’).value( ‘Settings’, { host: ‘example.com’ } ); angular.module(‘myApp’).constant( ‘Config’, { host: ‘example.com’ } ); angular.module(‘myApp’).config( function(Config, MyServiceProvider ) { MyServiceProvider.setApiHost( Config.host ); }); angular.module(‘myApp’).controller( ‘myCtrl’, function( Settings, $http ) { var _this = this; $http( Settings.host + ‘/api/data’ ).success( function(data) { _this.data = data; }); });
  • 18. Filters Filters are used for formatting data displayed to the user. Primarily used in expressions, but can be used in controllers and services also. {{ expression | filter1 | filter2 | ... }} <span>{{ article.published | date:”yyyy-M-d” }}<span> <span>{{ item.price | currency:”€” }}</span> <label>{{ ‘ITEM_PRICE’ | translate }}</label> <div ng-repeat=”person in persons | orderBy:’lastName’ | limitTo: 10”>{{ person.lastName}}</div> // TIP: json filter is handy to check what object contains <pre>{{ obj | json }}</pre>
  • 19. Built-in filters ● currency - Format currency ( symbol, how many decimal numbers) ● number - To string, how many decimal numbers to use ● date - Format Date to string, use locale format as default ● json - Object to JSON string ● lowercase - Converts string to lowercase ● uppercase - Converts string to uppercase ● filter - select subset of array ● limitTo - creates new array with specified number of elements ● orderBy - Order array by the expression
  • 20. Custom filter app.filter( ‘translate’, function( LocalizationService ) { return function( str ) { return LocalizationService.getTranslation( str ); }; }); app.constant( ‘Settings’, { dateFormat: ‘d.M.yyyy’ } ); app.filter( ‘formatDate’, function( $filter, Settings ) { var dateFilter = $filter.get(‘date’); return function( date ) { return dateFilter( date, Settings.dateFormat ); } }); app.filter( ‘fullName’, function() { return function( person ) { return person.firstName + ‘ ‘ + person.lastName; }; });
  • 21. Directives A Directive can be anything, it can either provide powerful logic to an existing specific element, or be an element itself and provide an injected template with powerful logic inside. Directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler to attach a specified behavior to that DOM element or even transform the DOM element and its children. Angular comes with a set of built-in directives: ng-model, ng-repeat, ng-show/ng-hide, ng-if, ng-click, ng-disabled, ng- mouseover, ng-blur, ng-src/ng-href, ng-class, ng-switch, ng-bind, ng-view ….
  • 22. Custom directives 1 Directives can match attribute name, tag name, comments or class name. Or restricted only to match some of them <my-dir></my-dir> <span my-dir="exp"></span> <!-- directive: my-dir exp --> <span class="my-dir: exp;"></span> Directives can emulate Shadow DOM behaviour with option transclude <my-element> Hi there! </my-element>
  • 23. Custom directives 2 app.controller(‘myCtrl, function() { this.person = { firstName: ‘John’, lastName: ‘Doe’ }; }); app.directive(‘person’, function() { return { template: ‘{{person.lastName}}, {{person.firstName}}’ }; }); <div ng-controller=”myCtrl”> <h1>Hello <person></person></h1>, <p>...</p> </div>
  • 24. Custom directives 3 app.directive(‘article’, function() { return { restrict: ‘EA’, scope: { article: ‘=article’ }, templateUrl: ‘article.html }; }); app.controller(‘myCtrl’, function() { this.article = { title: ‘Headline’, content: ‘Lore ipsum’, published: 1234554543543, author: ‘John Doe’ } }); article.html: <article> <header> <h1>{{article.title}}</h1> <p>Posted by {{ article.author }}</p> <p>{{ article.published | date: ‘d.M.yyyy’ }}</p> </header> <p>{{ article.content }}</p> </article> index.html: <article=”myCtrl.article”></article> <div article=”MyCtrl.article”></div>
  • 25. Custom directives 4 app.directive(‘article’, function() { return { restrict: ‘E’, scope: { data: ‘=data }, bindToController: true, templateUrl: ‘article.html, controlelrAs, ‘article’, controller: function() { this.addComment = function(msg) { this.data.comments.push(msg); this.data.$save(); } } }; }); <article> <header> <h1>{{article.data.title}}</h1> </header> <p>{{ article.data.content }}</p> <div class=comments> <ul> <li ng-repeat=”comment in article.data.comments”>{{ comment }}</li> </ul> <input ng-model=”newComment”/> <button ng-click=”article.addComment(newComment)”>Send</button> </div> </article>
  • 26. Custom directive 5 (transclude) app.directive(“hideable”, function() { return { replace: true, transclude: true, template: [ ‘<div ng-init=”hide=false”>’, ’<button ng-click=”hide=!hide”>Show/Hide</button>’, ‘<div ng-transclude ng-hide=”hide”></div>’, ‘</div>’ ].join(‘’) }; }); <div> <h1> {{ title }} </h1> <hideable> <h2>{{ subTitle }}</h2> <p>{{ content }}</p> </hideable> </div> <div> <h1> {{ title }} </h1> <div ng-init=”hidden=false”> <button ng-click=”hidden=!hidden”>Show/Hide</button> <div ng-hide=”hidden”> <h2>{{ subTitle }}</h2> <p>{{ content }}</p> </div> </div> </div>
  • 27. Directive configuration priority: 0, template: '<div></div>', // or templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... }, transclude: false, restrict: 'A', templateNamespace: 'html', scope: false, controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... }, controllerAs: 'stringAlias', bindToController: false, require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'], compile: function compile(tElement, tAttrs, transclude) { return { pre: function preLink(scope, iElement, iAttrs, controller) { ... }, post: function postLink(scope, iElement, iAttrs, controller) { ... } } }, // or // link: function postLink( ... ) { ... }
  • 28. Forms Form and controls provide validation services, so that the user can be notified of invalid input. This provides a better user experience, because the user gets instant feedback on how to correct the error.
  • 29. Forms <form name=”myFrom” novalidate> <label>Email:</label> <input type=”email” name=”email” ng-model=”user.email” required /> <label>Password:</label> <input type=”password” name=”password” ng-model=”user.password” required minlength=”8” /> <div ng-messages=”myForm.password.$error”> <div ng-message=”required”>Password is required</div> <div ng-message=”minlength”>Password is too short</div> </div> <button ng-disabled=”myForm.$invalid”>Submit</button> </form>
  • 30. Form CSS classes ● ng-valid: the model is valid ● ng-invalid: the model is invalid ● ng-valid-[key]: for each valid key added by $setValidity ● ng-invalid-[key]: for each invalid key added by $setValidity ● ng-pristine: the control hasn't been interacted with yet ● ng-dirty: the control has been interacted with ● ng-touched: the control has been blurred ● ng-untouched: the control hasn't been blurred ● ng-pending: any $asyncValidators are unfulfilled
  • 31. Form CSS class example <form name=”myFrom” novalidate> <label>Email:</label> <input type=”email” name=”email” ng-model=”user.email” required /> </form> <style type="text/css"> form input.ng-invalid.ng-dirty { outline-color: #FA787E; } </style>
  • 32. Form validators HTML5 input validators are built-in to Angular: number, email, required, url, time, date, .. Create own validators with directives: <input name=”pwd” type=”password ng-model=”user.password” required minlength=”8” validate-password-characters /> <div ng-messages=”myFrom.pwd.$error”> <div ng-message=”required”>Password is required</div> <div ng-message=”minlength”>Password is too short</div> <div ng-message=”passwordCharacters”>Your password must contain a numeric, uppercase and .. </div> </div>
  • 33. Custom validator app.directive('validatePasswordCharacters', function() { var REQUIRED_PATTERNS = [ /d+/, //numeric values /[a-z]+/, //lowercase values /[A-Z]+/, //uppercase values /W+/, //special characters /^S+$/ //no whitespace allowed ]; return { require : 'ngModel', link : function($scope, element, attrs, ngModel) { ngModel.$validators.passwordCharacters = function(value) { var status = true; angular.forEach(REQUIRED_PATTERNS, function(pattern) { status = status && pattern.test(value); }); return status; }; } } });
  • 34. Async validator angular.module(‘myApp’).directive(‘validateUsernameAvailable’, function($http) { return { require: ‘ngModel’, link: function( scope, element, attr, ngModel ) { ngModel.$asyncValidators.usernameAvailable = function(username) { return $http.get(‘/api/username-exists?username=’ + username ); } } }; }); <input type=”text” name=”myUsername” validate-username-available /> <div ng-if="myForm.myUsername.$pending"> Checking Username… </div> <div ng-if="myForm.myUsername.$error.usernameAvailable"> User name is in use </div> <button ng-disabled=”!myForm.$valid”>Submit</button>
  • 35. ngModelOptions Validation and specially async validation may cause too many calls for validation. With ngModelOptions you can control when ngModel is updated and validators are executed. // Update when leaving input element <input ng-model=”value” ng-model-options=”{ updateOn:’blur’ }” required /> // Update only when no changes in 500ms or immediately when leaving element <input ng-model=”username” ng-model-options=”{ debounce: { default: 500, blur: 0 } }” required validate-username-available />
  • 36. Events Angular scope have built-in event framework. ● $on - listen to event ● $emit - send event to upwards (self and parent scopes) ● $broadcast - send event to downwards (self / child scopes) <div ng-controller="EventCtrl as parentCtrl" ng-scope> <div ng-controller="EventCtrl as childCtrl1" ng-scope> <div ng-controller="EventCtrl as subChildCtrl" ng-scope></div> </div> <div ng-controller="EventCtrl as childCtrl2" ng-scope> </div> </div> $broadcast $send
  • 37. Angular extension modules ● ngRoute - Routing and deeplinking ● ngResource - RESTful services ● ngAnimate - Support for JS, CSS transitions and animations hooks ● ngSanitize - Bind HTML content safe way ● ngTouch - Touch events ● ngMessages - Enhanced support to show messages
  • 38. ngRoute To create routing for your Angular application include ngRoute module and defined routes in config()-function. angular.module(´myApp´, [´ngRoute´]).config( function( $routeProvider, $locationProvider ) { $routeProvider .when('/', { templateUrl: 'main.html', controller: ´mainController´ }). .when('/page1', { templateUrl: page1.html', controller: ´page1Controller´ }). .otherwise({ redirectTo: ´/´ }); $locationProvider.html5Mode(true); }); index.html: <body> <div ng-view> Route content will be here </div> main.html: <h1>main page</h1> <a href=”/page”>goto to sub page</a> page.html: <h1>Page1 </h1> <a href=”/”>back to main page</a>
  • 39. ngRoute - resolve content angular.module('myApp').config( function($routeProvider) { $routeProvider. when("/article/:id", { templateUrl: 'article.html', controller: 'ArticleCtrl', controllerAs: ‘articleCtrl’, resolve: { article: function($resource, $route, $q, $location) { var Article = $resource(‘/api/article/:id’); var request = Article.get({id: $route.current.params.id}); request.$promise.catch( function() { $location.path(‘/notfound’); $location.replace(); }); return request.$promise; } } }); }); angular.module(‘myApp’) .controller( ‘articleCtrl’, function( article ) { this.data = article; });
  • 40. ngResource Factory service which creates a resource object that lets you to interact RESTful API. Makes data handling object oriented. var User = $resource( ‘/api/user/:id’, { id: ‘@_id’ }, { update: { method: ‘PUT’ } }); var person = new User({ firstName: ‘John’, lastName:’doe’ }); person.$save(); person.lastName = ‘Doe’; person.$update(); var person = new User({ firstName: ‘John’, lastName:’doe’ }); person.$save(); // POST: ‘/api/user’ person.lastName = ‘Doe’; person.$update(); // PUT: ‘/api/user/1’ // GET: ’/api/user?firstName=John’ var users = User.query({ firstName: ‘John }); var john = User.get({ id: 1234 }, function() { john.lastLogin = new Date(); john.$update(); });
  • 41. ngResource Default configuration: { 'get': {method:'GET'}, 'save': {method:'POST'}, 'query': {method:'GET', isArray:true}, 'remove': {method:'DELETE'}, 'delete': {method:'DELETE'} };
  • 42. ngResource var Article = $resource(‘/api/article/:id’, { id: ‘@_id’ }, { recent: { method: ‘GET’, isArray: true, cache: true, // use http cache for method params: { limit: 10, latest: true } } }); // GET: /api/article?limit=10&latest=true&type=news var latestArticles = Article.$latest( { type: ‘news’ } ); latestArticles.$promise .success( function() { // articles loaded }) .catch( function() { // request failed });
  • 43. ngAnimate Adds animation hooks for common directives such as ngRepeat, ngView and ngShow. Also pays attention to CSS class changes with ngClass by triggering add and remove hooks. When change is triggered it places state CSS class, like ng-hide, and end state ng-hide-active. And after animation is ended it removes those classes
  • 44. ngShow animate <button ng-click=”hide=!hide”>Show/hide</button> <div class=”animate” ng-show=”hide”> Shown/hide with animation </div> <style> .animate { opacity: 1; } .animate.ng-hide { opacity: 0; } .animate.ng-hide-add, .animate.ng-hide-remove { -webkit-transition: 1s linear all; transition: 1s linear all; } </style>
  • 45. JS animation with jQuery angular.module('myApp',['ngAnimate']).animation('.animate', function() { return { beforeAddClass: function(element, className, done) { if( className === 'ng-hide' ) element.animate({ opacity: 0 }, 500, done ); else done(); }, removeClass: function(element, className, done) { if( className === 'ng-hide' ) element.css({ opacity: 0 }).animate({ opacity: 1}, 500, done ); else done(); } } })
  • 46. Testing AngularJS is designed that applications are testable. Dependency Injection makes testing easier, by allowing inject mock instead of real module.
  • 47. Unit testing with Karma my-ctrl.js: angular.module('myApp',[]) .controller('myCtrl', function( $http ) { var _this = this; $http.get('/api/data').success(function(data) { _this.data = data; }); this.isOk = function() { return this.data && this.data.ok; } }); my-ctrl.spec.js: describe('controller:myCtrl', function() { beforeEach( module('myApp') ); it('should fetch data from server and return ok', inject(function($controller, $httpBackend) { $httpBackend .when('GET', '/api/data') .respond({ ok: true }); $httpBackend.expectGET('/api/data'); var ctrl = $controller( 'myCtrl' ); expect(ctrl.isOk()).toBe(false); $httpBackend.flush(); expect(ctrl.isOk()).toBe(true); }) ); });
  • 48. Dependency Injection in testing it('should fetch data from server and return ok', inject(function($controller) { var ctrlCB; var myHttpMock = { get: function() { return { success: function(cb) { ctrlCB= cb; } }; } } var ctrl = $controller( 'myCtrl', { $http: myHttpMock } ); expect(ctrlCB).not.toBe(undefined); cb( { ok: true } ); expect(ctrl.isOk()).toBe( true ); }));
  • 49. End-to-end testing with protractor describe('password view', function() { it('should show error when too short input', function() { browser.get('http://localhost:63342/angular-training/protractor/index.html'); element(by.model('user.password')).sendKeys('test'); var messages = element(by.id('password.error')); expect(messages.getText()).toContain('short'); element(by.model('user.password')).sendKeys('test12345ABC-'); element(by.buttonText(‘save’)).click(); }); });
  • 50. Best practices ● Design UI/HTML first! Create HTML first and then just add functionality with Angular. Style guide + UI mock-ups ● Avoid using $scope directly By eliminating usage of $scope, code is closer to 2.0 style ● Avoid using ng-controller in HTML Use through route or directives, do not add them directly. ● Testing is easy! Write tests for your code / site
  • 51. Best practices ● If repeating elements in HTML, create directive for them ● Create services and use $resource to access server APIs ● Do not format data in the controllers, which will be displayed in the view, instead use filter. Example, localisation, date/time, currency, etc. Create filters that do it for you, and you can then modify those filters and reflect changes to whole site. ● Avoid long lists which contains lots of bind data, that can cause performance issues. Use paging to limit elements, if data changes in page, otherwise use one-time binding (Angular 1.3), or libraries like ‘bindonce’ for Angular 1.2 ● If you are binding without dot, you are probably doing something wrong. {{ name }} = BAD, {{ user.name }} = GOOD ● Keep code structured
  • 52. Caveats ● 2000 watches is considered as saturation point, after that page rendering may seem slow ● Use directive isolated scope only when needed. Specially with transclude, it can cause problems not to be able to access variables ● Namespace Modules does not add namespace for functions. Plan function naming (controller/service/directive/filter) ● Dependency Injection and javascript minify DI breaks when minified. Declare in array syntax or use ngAnnote/ngMin ● When using 3rd party libraries etc, remember to call $apply to get changes render to page
  • 53. Tools & Utilities for AngularJS Boilerplates https://github.com/SC5/gulp-bobrsass-boilerplate/tree/angularjs https://github.com/DaftMonk/generator-angular-fullstack Testing: http://angular.github.io/protractor/#/ http://karma-runner.github.io/0.12/index.html http://www.ng-newsletter.com/advent2013/#!/day/19 Build and minification: https://github.com/olov/ng-annotate
  • 54. More about AngularJS Community in Helsinki capital area https://www.facebook.com/groups/helsinkijs/ http://frontend.fi/ AngularJS Primer https://www.airpair.com/angularjs/posts/angularjs-tutorial https://thinkster.io/angulartutorial/a-better-way-to-learn-angularjs/ http://lostechies.com/gabrielschenker/2013/12/05/angularjspart-1/ Blogs that have good information about AngularJS: http://www.yearofmoo.com/ http://www.jvandemo.com/ Good reads: http://sc5.io/posts/how-to-implement-loaders-for-an-angularjs-app http://teropa.info/blog/2014/11/01/why-i-think-angular-2-will-still-be-angular.html
  • 55. Conclusion and discussion What did we learn? Discussion about AngularJS
  • 56. Test setup ● Install Node.js for test server http://nodejs.org/download/ ● Download and extract training examples https://docs.google.com/a/sc5.io/uc? authuser=0&id=0B_18Pna_ughFNWVZaUV1amV6bjA&export=download ● Go to exercises folder and execute commands > npm install > npm start ● Open local web server with browser http://localhost:3000/