What I've learned after reading...
#BDXIO17
Emmanuel DEMEY
Zenika Lille
EmmanuelDemey
Décorateurs
Fetch
Metadata Reflection API
@angular/cli
ECMAScript 2015
Shadow DOM
PWA
Custom Elements
DOM
Zones
Intl
WebWorkers
Intl
async
decorators
zones
Intl API
Internationalization API
Manipuler une donnée en fonction d'une locale
- Collator
- NumberFormat
- DateTimeFormat
- PluralRules
Internationalization API
new Intl.Collator(locale, options)
String.prototype.localeCompare(locale, options)
new Intl.DateTimeFormat(locale, options)
Date.prototype.toLocaleString(locale, options)
Date.prototype.toLocaleDateString(locale, options)
Date.prototype.toLocaleTimeString(locale, options)
new Intl.NumberFormat(locale, options)
Number.prototype.toLocaleString(locale, options)
DateTimeFormat
let formatter = new Intl.DateTimeFormat(“en”,{});
formatter.format(new Date(Date.UTC(2017,11,25,3,0,0)))
let formatter = new Intl.DateTimeFormat(“fr”,{
month: “long”
day: “numeric”, /* 2-digit */
year: “numeric”, /* 2-digit */
hour: “numeric”, /* 2-digit */
minute: “numeric”, /* 2-digit */
});
formatter.format(new Date(Date.UTC(2016,10,10,3,0,0)));
12/25/2017
25/12/2017
décembre
25 décembre 2017
25 décembre 2017 04h
25 décembre 2017 04h00
NumberFormat
let formatter = new Intl.NumberFormat(“en”,{});
formatter.format(1000.59)
let formatter = new Intl.NumberFormat(“fr”,{
style: “currency”, /* percent, number */
currency: “EUR”, /* USD */
currencyDisplay: “name”, /* symbol */
useGrouping: false,
maximumFractionDigits: 1
});
formatter.format(1000.57);
1,000.59
1 000,59
1 000,59 euros
1000,59 euros
1000,6 euros
Vous avez dit ?
@Pipe({name:”number”})
class NumberPipe { }
@Pipe({name:”percent”})
class PercentPipe { }
@Pipe({name:”currency”})
class CurrencyPipe { }
@Pipe({name:”date”})
class DatePipe { }
Vous avez dit ?
{{ price | currency:”EUR”:true:4.2-2 }}
Mettons nos mains dans le cambouis
Mauvaise Nouvelle...
Mauvaise Nouvelle...
- Nouvelle implémentation en Angular 5.x
- Nombreux Bugs avec l'implémentation Intl
- Attention potentiels breaking changes
- Anciennes versions toujours disponibles (pout l'instant)
import { NgModule } from '@angular/core';
import { CommonModule, DeprecatedI18NPipesModule }
from '@angular/common';
@NgModule({
imports: [
CommonModule,
// import deprecated module after
DeprecatedI18NPipesModule
]
})
export class AppModule { }
Async
@Component({
template: `{{ user }}`
})
export class AppComponent {
user: string;
constructor(private httpClient: HttpClient){
httpClient.get('/api/data')
.subscribe(data => this.user = data);
}
}
@Component({
template: `̀{{ user$ | async }}`
})
export class AppComponent {
user$: Observable<string>;
constructor(private httpClient: HttpClient){
this.user$ = httpClient.get('/api/data');
}
}
@Pipe({
name: 'async',
pure: false
})
export class AsyncPipe {
}
Pipe impure
Mettons nos mains dans le cambouis
Decorators
Les décorateurs
Fonctions pour ajouter des métadonnées à des objets JS (Property, Method, Class, Parameter...)
Les décorateurs
@Input
public props: string;
function Input( … ){
}
Les Factories
@Input(“inputName”)
public props: string;
function Input(inputName){
return function(...) { }
}
Les différentes signatures
declare type ClassDecorator = (target: Function) => Function
declare type PropertyDecorator =
(target: Object, propertyKey: string) => void;
declare type MethodDecorator =
(target: Object, propertyKey: string, descriptor:
TypedPropertyDescriptor) => TypedPropertyDescriptor;
declare type ParameterDecorator =
(target: Function, propertyKey: string,
parameterIndex: number) => void;
Mon 1e décorateur
@log sayHello(){ … }
function log(target,key,descriptor){
let orig = descriptor.value;
descriptor.value = function(...args){
console.log(“function called”);
return orig.apply(this, args);
}
return descriptor;
}
Mon 2e décorateur
@Injectable
class DevFestService {
constructor(service: Service) { }
}
function Injectable(target){
let original = target;
let newC = function(...args){
args = args.map(s => injector.get(s));
return original.apply(this, args);
}
newC.prototype = original.prototype;
return newC;
}
Oui..., mais au Runtime ?
var __decorate = function () { … };
function Injectable(target) { … }
var DevFestService = (function () {
function DevFestService() {...}
DevFestService = __decorate([
Injectable
], DevFestService);
return DevFestService;
}());
Vous avez dit ?
-
Définir les éléments Angular2
-
Injection de Dépendances
-
Créer des Inputs / Outputs
-
Accéder aux éléments HTML
-
Intéragir avec l’élément host
Vous avez dit ?
//<button click-handler>Click Me</button>
@Directive({ selector: ‘[click-handler]’})
export class ClickHandler {
@Input() parameter: string;
constructor(@Inject(LOCALE_ID) locale) {}
@HostBinding(‘click’)
click(){ … }
}
Les Zones
startTimer()
goToBdx();
setTimeout( _ => {
veryLongTask()
}, 0);
setTimeout( _ => {
veryLongTask()
}, 0);
goBackToLille();
endTimer()
Hooks for the Event Loop
Création d'une Zone
zone.fork( specConfig )
.run(function(){
...
});
ZoneSpec
interface ZoneSpec {
onScheduleTask: () => {},
onInvokeTask: () => {},
onHandleError: () => {},
onHasTask: () => {}
}
Monkey Patch
window.setTimeout = function(c, time){
Zone.current.onScheduleTask();
setTimeout(function(){
Zone.current.onInvokeTask();
try {
c();
} catch (e){
Zone.current.onHandleError()
}
}, time);
}
Vous avez dit ?
- Change Detection
- StackTraces complètes
Vous avez dit ?
Désactivation des zones :
-
Animations
-
Analytics
-
Evénements trop fréquents
Vous avez dit ?
class AnalyticsService {
constructor(
private zone:NgZone,
private http: HttpClient){
}
sendToAnalitics(){
this.zone.runOutsideAngular(() => {
this.http.post(“/api/analytics”, {})
.subscribe(...);
});
}
}
Emmanuel DEMEY
Zenika Lille
EmmanuelDemey
Noun Project
https://thenounproject.com/
Copy of deck
By Emmanuel Demey
Copy of deck
- 1,920