technozaure - angular2
TRANSCRIPT
Emmanuel
DEMEYConsultant & Formateur Web
Zenika Nord
@EmmanuelDemey
Web / Domotique / Histoire / Biérologie
API des Directivesapp.directive('MyDirective', function(){ return { restrict: 'AE', require: '?^^ngModel', scope: { variable: '@' }, compile: function(...) { return { pre: function(...) { ... }, post: function(...) { ... } } }, link: function(...) { ... } }});
app.directive('MyDirective', function(){ return { restrict: 'AE', require: '?^^ngModel', scope: { variable: '@' }, compile: function(...) { return { pre: function(...) { ... }, post: function(...) { ... } } }, link: function(...) { ... } }});
API des Directives
app.directive('MyDirective', function(){ return { restrict: 'AE', require: '?^^ngModel', scope: { variable: '@' }, compile: function(...) { return { pre: function(...) { ... }, post: function(...) { ... } } }, link: function(...) { ... } }});
API des Directives
app.directive('MyDirective', function(){ return { restrict: 'AE', require: '?^^ngModel', scope: { variable: '@' }, compile: function(...) { return { pre: function(...) { ... }, post: function(...) { ... } } }, link: function(...) { ... } }});
API des Directives
Mais aussi...
Pas de Server-Side Rendering
Gestion des événements (ngClick, ...)
Gestion des attributs HTML (ngSrc, ...)
Architecture Angular 2
<app></app>
menu grid
gallery
DI
(classes ES6 ou TypeScript)
Pipes
(classes ES6 ou TypeScript)
Composants Angular 2
Ressources de base en Angular 2
Tout est composant
Application représentée par un arbre
de composants
Utilisation de métadonnées pour
configurer un composant
//<my-app></my-app>function MyAppComponent() {
}
MyAppComponent.annotations = [ new angular.ComponentAnnotation({ selector: 'my-app' }), new angular.ViewAnnotation({ template: "<main>" + "<h1> This is my first Angular2 app</h1>" + "</main>" })];
Composant version ES5
import {Component, View} from 'angular2/angular2';
@Component({selector: 'my-app'})@View({ template: `<main> <h1> This is my first Angular2 app</h1> </main>`})class MyAppComponent {
}
Composant version TypeScript
import {Component, View, bootstrap} from 'angular2/angular2';@Component({selector: 'my-app'})@View({ template: `<main> <h1> This is my first Angular2 app</h1> </main>`})class MyAppComponent {
}bootstrap(MyAppComponent);
Bootstrap de l'Application
Property Binding
<input [attr]="expression" />
Accès à toutes les propriétés des éléments
HTML
Possibilité de définir de nouvelles propriétés
Compatibilité avec d'autres spécifications
Property Binding//<beerItem [beer]="'Maredsous'"></beerItem>@Component({ selector: 'beerItem', properties: ['beer']})@View({ template: `<section> <h2>{{beer}}</h2> <button>Je veux celle-ci !</button> </section>`})class BeerItem{ beer: String;
}
Event Binding
<input (event)="expression" />
Accès à tous les événements des éléments
HTML
Possibilité de définir de nouveaux événements
Event Bindings//<beerItem [beer]="'Maredsous'" (selectBeer)="sendToBeerTap()"></beerItem>@Component({ selector: 'beerItem', properties: ['beer'], events: ['selectBeer']})@View({ template: `<section> <h2>{{beer}}</h2> <button (click)="selectItem()">Je veux celle-ci !</button> </section>`})class BeerItem { beer: String; selectBeer: EventEmitter; selectItem() { this.selectBeer.next(this.beer); }}
“ Attribute names must consist of one or
more characters other than the space
characters, U+0000 NULL, """, "'", ">", "/",
"=", the control characters, and any
characters that are not defined by Unicode.
Syntaxe valide ?
Component Dependency
Nécessité d'importer les composants
nécessaires à votre application
Propriété directives de @View
Component Dependencyimport {Component, View, bootstrap, NgFor} from 'angular2/angular2';import {BeerItem} from 'BeerItem';
@Component({ selector: 'my-app'})@View({ template: `<main class="mdl-layout__content"> <ul class="googleapp-card-list"> <li *ng-for="#beer of beers"> <beerItem [beer]="beer"></beerItem> </li> </ul> </main>`, directives: [NgFor, BeerItem]})class MyAppComponent { public beers: String[] = []; constructor() { }}
Injection de Dépendances
Code métier dans des services
Chaque Service est un singleton
Principe d'Hollywood
Multiples implémentations en NG1 !
Injection de Dépendances
app.service('TapService', function($http){ this.getBeer = function(beerId){ return $http.get('/api/i-am-thirsty/' + beerId); };});
app.controller('AppCtrl', function(TapService){ this.selectBeer = function(idBeer){ return TapService.getBeer(idBeer); }});
DI version Angular2
1 Injecteur principal + 1 Injecteur par composant
Hérite de l'injecteur parent
Possibilité de redéfinir le Service à injecter
Utilisation d'annotations en ES6 et des types en
TypeScript
Services disponibles via le constructeur du
composant
Injecteur Principal - toValue
@Component({selector: 'my-app'})@View({ template: `<main> <h1> Welcome to our {{breweryName}}</h1> </main>`})class MyAppComponent { constructeur(public breweryName:String){ }}
bootstrap(MyAppComponent, [bind(String).toValue('Zenika Brewery')]);
Injecteur Principal - toClass
@Component({selector: 'my-app'})@View({ template: `<main> <h1> Welcome to our {{breweryName}}</h1> </main>`})class MyAppComponent { constructeur(private breweryService:BreweryService){ this.breweryName = this.breweryService.getBreweryName(); }}
bootstrap(MyAppComponent, [bind(BreweryService).toClass(BreweryService)]);
Injecteur Principal - toClass@Component({selector: 'my-app'})@View({ template: `<main> <h1> Welcome to our {{breweryName}}</h1> </main>`})class MyAppComponent { constructeur(private breweryService:BreweryService){ this.breweryName = this.breweryService.getBreweryName(); }}
bootstrap(MyAppComponent, [BreweryService]);
Injecteur Principal -
toFactory@Component({selector: 'my-app'})@View({ template: `<main> <h1> Welcome to our {{breweryName}}</h1> </main>`})class MyAppComponent { constructeur(public breweryName:String){ }}
bootstrap(MyAppComponent, [bind(String) .toFactory((BreweryService) => { return BreweryService.getBreweryName(); }, [BreweryService])]);
Child Injector
@Component({selector: 'my-app'})@View({ template: `<main> <welcome-message></welcome-message> </main>`, directives: [WelcomeMessage]})class MyAppComponent { constructeur(public breweryName:String){ }}
bootstrap(MyAppComponent, [bind(String).toValue('Zenika Brewery')]);
Child Injector
@Component({ selector: 'welcome-message'})@View({ template: `<h1>Welcome to our {{breweryName}}</h1>`})class WelcomeMessage{ constructeur(public breweryName:String){ }}
Child Injector
@Component({ selector: 'welcome-message'})@View({ template: `<h1>Welcome to our {{breweryName}}</h1>`, bindings: [ bind(String).toValue('Awesome Zenika Brewery') ]})class WelcomeMessage{ constructeur(public breweryName:String){ }}
Pipes
Identiques aux filtres d'AngularJS 1
Permet de manipuler une donnée
Utilisation d'une classe annotée @Pipe
Pipes disponibles dans le framework :
upperCase, lowerCase, Async,
Number, limitTo, json et date
Pipes
import {Pipe} from 'angular2/angular2';
@Pipe({ name: 'UpperCasePipe'})export class UpperCasePipe implements PipeTransform { transform(value: String, args: any[]) { return value.toUpperCase(); }}
Pipes
import {Component, View} from 'angular2/angular2';import {UpperCasePipe} from './UpperCasePipe.ts'
@Component({ selector: 'comp'})@View({ template: `<div>{{'Démo utilisant les pipes' | UpperCasePipe}}</div>`, pipes: [UpperCasePipe]})export class Component{}
Pipesimport {Component, View} from 'angular2/angular2';import {UpperCasePipe} from './UpperCasePipe.ts'
@Component({ selector: 'comp'})@View({ template: ``, bindings: [UpperCasePipe] })export class Component{ constructor(public upperCasePipe:UpperCasePipe){ this.upperCasePipe.transform('Un autre exemple...'); }}
@View
@Animation
@Inject
@InjectLazy
@Optional
@Host
@Parent
@Pipe
@Property
@Event
@RouteConfig
@HostBinding
@HostEvent
@ContentChild
@ContentChildren
@ViewChildren
Repository Github
Documentation
http://blog.thoughtram.io/
NG Europe 2014
NG Conf 2015
AngularU
ESLint Plugin Angular
John Papa Styleguide