The power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect.
— Sir Tim Berners-Lee
@olivierleplus
Olivier Leplus
@olivierleplus
DevRel at Microsoft
Global network of experienced, designers and developers that actively support developers and startups.
Around 1 billion people live with some form of disability.
— World health organisation
Law
<div></div>
<span></span>
<a id="addUser" class="btn">
Add new user
</a>
<button id="addUser" class="btn" aria-label="Add new user">
Add new user
</button>
All page functionality is available using the keyboard, unless the functionality cannot be accomplished in any known way using a keyboard (e.g., free hand drawing).
TIME
TO LEARN ANGULAR 2
ES5
ES2015
ES2016
TS
ES+
you should learn TypeScript
you must
learn ES6+
bit.ly/learn-es2015 - Discover ES6 (french only)
YOUR APP
IS A TREE OF
SELF-DESCRIBING
MODULES & COMPONENTS
<my-menu [items]="mainMenu"></my-menu>
<img [src]="imageUrl" />
THREE
TYPES OF DIRECTIVES
STRUCTURAL
CHANGES THE DOM LAYOUT
<li
*ngIf="isFooBar"
*ngFor="let card of dataStore.items;
trackBy:customTrackBy">
</li>
STRUCTURAL
<my-items-card *ngFor="let card of dataStore.items;
trackBy:customTrackBy">
{{ card }}
</my-items-card>
<!-- is equivalent to this -->
<template ngFor let-card [ngForOf]="dataStore.items"
[ngForTrackBy]="customTrackBy">
<my-items-card>{{ card }}</my-items-card>
</template>
ATTRIBUTES
CHANGES THE BEHAVIOR OF THE ELEMENT
<div
[style.width.px]="mySize">
</div>
ATTRIBUTES
import {
Directive,
ElementRef,
Renderer,
} from '@angular/core';
@Directive({
selector: '[myHighlight]'
})
export class MyHighlightDirective {
constructor(el: ElementRef, renderer: Renderer) {
renderer
.setElementStyle(
el.nativeElement,
'backgroundColor',
'yellow'
);
}
}
<span myHighlight >Highlight me!</span>
import {Directive, ElementRef, Renderer} from '@angular/core';
@Directive({
selector: '[x-large]'
})
export class XLarge {
constructor(element: ElementRef, renderer: Renderer) {
renderer.setElementStyle(
element.nativeElement, 'fontSize', 'x-large'
);
}
}
DO NOT EVER NEVER TOUCH THE DOM!
renderer.setElementStyle(
el.nativeElement,
'backgroundColor',
'yellow'
);
COMPONENT
JUST A DIRECTIVE WITH A TEMPLATE
<my-component>
Loading...
</my-component>
COMPONENT
COMPONENTS CAN DISPLAY FORMATTED DATA
THANKS TO
PIPES
JUST LIKE
ANGULAR 1
FILTERS
BUILT-INS PIPES
DatePipe,
UpperCasePipe,
LowerCasePipe,
CurrencyPipe,
PercentPipe...etc
CUSTOM PIPE
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'trim'
})
export class TrimPipe implements PipeTransform {
transform(value: any) {
if (!value) {
return '';
}
return value.trim();
}
}
PIPES CAN BE STATEFUL
ASYNC PIPE
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'fetch',
pure: false
})
export class FetchJsonPipe {
private fetchedValue:any;
private fetchPromise:Promise<any>;
transform(value:string, args:string[]):any {
this.fetchPromise = window.fetch(value)
.then((result:any) => result.json())
.then((json:any) => this.fetchedValue = json);
return this.fetchedValue;
}
}
ASYNC PIPE
<div>
{{'heroes.json' | fetch | json}}
</div>
COMPONENTS
CAN HAVE
STATE
[ property binding ]
( event binding )
import {Component, Input, AfterViewInit, EventEmitter} from '@angular/core';
@Component({
/* configuration */
})
export class ThemeCard implements AfterViewInit {
@Input() inputProperty: string;
@Output() outputEvent: EventEmitter<string>;
constructor() {
this.outputEvent = new EventEmitter<string>();
}
ngAfterViewInit() {
console.log(this.inputProperty);
}
onClick() {
this.outputEvent.emit('foo');
}
}
COMPONENTS ARE
ROUTABLE
// app.routes.ts
import { RouterModule } from '@angular/router';
import { CatComponent } from './cats/';
const routes = [
{path: '', redirectTo: 'cat'},
{path: 'cat', component: CatComponent}
];
export const Routes = RouterModule.forRoot(routes);
// app.routes.ts
import { RouterModule } from '@angular/router';
import { CatComponent } from './cats/';
const routes = [
{path: '', redirectTo: 'cat'},
{path: 'cat', loadChildren: 'app/cat/cat.module#CatModule'}
];
export const Routes = RouterModule.forRoot(routes);
// app.routes.ts
import { RouterModule } from '@angular/router';
import { CatComponent, AuthGuard, CatResolver } from './cats/';
const routes = [
{path: '', redirectTo: 'cat'},
{
path: 'cat',
canActivate: [ AuthGuard ],
resolve: { cats: CatResolver },
loadChildren: 'app/cat/cat.module#CatModule'
}
];
export const Routes = RouterModule.forRoot(routes);
import { NgModule } from '@angular/core';
import { Routes } from './app/app.routes';
@NgModule({
imports: [ ..., Routes ],
...
})
// app.component.ts
@Component({
selector: 'my-app',
template: `
<h1>Component Router</h1>
<nav>
<a [routerLink]="['cat']">Cat</a>
</nav>
<router-outlet></router-outlet>
`
})
export class AppComponent {
constructor() {}
}
COMPONENTS CAN USE
SERVICES
import { Component } from '@angular/core';
import { DataStore } from './my-store.service';
@Component({
selector: 'home',
providers: [ DataStore ],
//...
})
export class Home {
private data: any[];
constructor(data: DataStore){
this.data = data.someAPI();
}
}
import { NgModule } from '@angular/core';
import { DataStore } from './my-store.service';
@NgModule({
providers: [ ..., DataStore ],
...
})
import { Component, provide } from '@angular/core';
import { DataStore } from './my-store.service';
@Component({
providers: [ DataStore ]
})
export class Home { /* */ }
{ provide: DataStore, useClass: DataStore }
// values
{provide: Token, useValue: 'Hello World' }
// aliases
{provide: DataStore, useClass: DataStore }
{provide: MockedDataStore, useExisting: DataStore }
// factories or configurable instances
{provide: DataStore, useFactory: (dep1, dep2) => {
return new DataStore(dep1, dep2);
},
deps: [Dep1, Dep2]
}
SUPPORTED LANGUAGES
EDITORS SUPPORT
Angular2 and TypeScript support
BUILD SYSTEMS
CHECK OUT THE NEW ANGULAR CLI
UPGRADING TO ANGULAR 2+ OFFICIAL DOCUMENTATION
(click on icon to open link)
THANKS TO FELLOW GDEs
Faster development and errors prevention, thanks to Classes, TypeScript and Decorators...
Set up the build system can be hard...
We have a CLI...
Faster change detection (up to 10x times faster) and faster overall performance (up to 2.5x times or more)...
People don't seem to like the template syntax...
Com'on, this is just syntax.
Future proof with support for web, mobile, server-side rendering and native...
Lack of convention?
The Style guides are here!
Great browser support. Internet Explorer 9 and plus...
Some developers are turned off by Dependency Injection...
sorry for you guys!
No long tied to the browser. Angular 2+ can run anywhere (server, mobile, web worker, etc.)...
SOME THOUGHTS...
A2 has all the concepts of A1 but is better in every way...
Your skills from A1 have already prepared you for A2...
Ng2 is built upon Web Standards, if you know the Web then you know ng2...
Ng2 is not just a framework, it is a modular platform.
manekinekko