Angular 2 @EmmanuelDemey
Emmanuel DEMEY Consultant & Formateur Web Zenika Nord @EmmanuelDemey Web / Domotique / Histoire / Biérologie
Les choses que nous n'aimons pas...
Architecture AngularJS MV* MV* MV*
Architecture AngularJS MV* MV* MV*
Architecture AngularJS DI (provider, service, factory...) MV* MV* MV*
Architecture AngularJS DI (provider, service, factory...) MV* MV* MV* Filtres
Architecture AngularJS DI (provider, service, factory...) MV* MV* MV* Filtres
API des Directives app.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
<input ng-model="firstName"> <p> {{firstName }} </p> 2-way data-binding
<input ng-model="firstName" ng-model-options="options"> <p> {{firstName }} </p> 2-way data-binding
<input ng-model="firstName"> <p> {{::firstName }} </p> 2-way data-binding
Et ce n'est pas fini...
Mais aussi... Pas de Server-Side Rendering Gestion des événements (ngClick, ...) Gestion des attributs HTML (ngSrc, ...)
La solution... Angular 2
Attention !
Version Alpha P(eu|as) de Doc
Architecture Composants Injection de Dépendance Pipes
Architecture Angular 2 <app></app>
Architecture Angular 2 <app></app> menu grid gallery
Architecture Angular 2 <app></app> menu grid gallery DI (classes ES6 ou TypeScript) Pipes (classes ES6 ou TypeScript)
La Famille JavaScript
La Famille JavaScript ES5
La Famille JavaScript ES5 ES2015
La Famille JavaScript ES5 ES2015
La Famille JavaScript ES5 ES2015 TypeScript
Les Web Components Custom Elements Templates Imports Shadow DOM
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
Binding Root Cpt Child1 Cpt Child2 Cpt [property]="expression" (event)="update()"
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 <body> <h1>My First Angular2 app</h1> </body>
Property Binding <body> <h1 [textContent]="'My First Angular2 app'"> </h1> </body>
Property Binding <body> <h1>{{'My First Angular2 app'}} </h1> </body>
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); } }
Syntaxe valide ?
“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 ?
Syntaxe valide ?
Component Dependency Nécessité d'importer les composants nécessaires à votre application Propriété directives de @View
Component Dependency import {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{}
Pipes import {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...'); } }
@Component @View@Directive
@View @Animation @Inject @InjectLazy @Optional @Host @Parent @Pipe @Property @Event @RouteConfig @HostBinding @HostEvent @ContentChild @ContentChildren @ViewChildren
Roadmap
Repository Github Documentation http://blog.thoughtram.io/ NG Europe 2014 NG Conf 2015 AngularU ESLint Plugin Angular John Papa Styleguide
Questions ?
Technozaure - Angular2

Technozaure - Angular2