26
26.09.2016 1 Angular 2: Die Ideen hinter Datenbindung und Formularen im Detail betrachtet Manfred Steyer ManfredSteyer Über mich … Manfred Steyer SOFTWAREarchitekt.at Trainer & Consultant GDE & MVP Focus: Angular 2 Page 2 ManfredSteyer

Angular 2: Die Ideen hinter Datenbindung und Formularen im Detail betrachtet

Embed Size (px)

Citation preview

26.09.2016

1

Angular 2: Die Ideen hinter Datenbindung und Formularen

im Detail betrachtet

Manfred Steyer

ManfredSteyer

Über mich …

• Manfred Steyer

• SOFTWAREarchitekt.at

• Trainer & Consultant

• GDE & MVP

• Focus: Angular 2

Page 2

ManfredSteyer

26.09.2016

2

Ziele

• Wie funktioniert die Datenbindung in Angular 2?

• Wie kann man die Performance für Datenbindung verbessern?• Immutables

• Observables

Nicht-Ziele

• Allgemeine Einführung in Angular 2

26.09.2016

3

Inhalt

• Überblick zur Datenbindung in Angular 2

• Datenbindung hinter den Kulissen

• Two-Way-Binding

• Performancetuning mit Immutables und Observables

• Formulare

Warum ist dieses Thema interessant?

• Grundlegender Mechanismus jedes SPA-Frameworks

• Beeinflusst Performance maßgeblich

• Two-Way-Binding für u. a. für Biz-Anwendungen

• Ansatzpunkte für Performanceoptimierungen

26.09.2016

4

Benchmark

Überblick zur Datenbindung in Angular 2

26.09.2016

5

Angular-2-Anwendung sind Komponenten

Page 9

@Component({selector: 'flug-suchen',templateUrl: 'flug-suchen.html'

})export class FlugSuchenComponent {

von: string;nach: string;fluege: Array<Flug>;

constructor(http: Http) { }

search() { [...] }select(flug) { [...] }

}

Page 10

<input [(ngModel)]="von"><input [(ngModel)]="nach">

<button [disabled]="!von || !nach" (click)="search()">Search

</button>

<table><tr *ngFor="let flug of fluege">

<td>{{flug.id}}</td><td>{{flug.datum}}</td><td>{{flug.von}}</td><td>{{flug.nach}}</td>

</tr></table>

Template

26.09.2016

6

Hinter den Kulissen

Page 11

Data-Binding in AngularJS 1.x

Page 12

Model Model Directive

26.09.2016

7

Komponentne-Baum in Angular 2

Page 13

Komponente für gesamte App

Komponente (z. B. list)

Komponente

(z. B. list-item)

Komponente

(z. B. list-item)

Regeln für Property Bindings

• Komponente hängt nur von Daten des Parent ab

• Komponente hängt nie von Daten der Kinder ab

• Abhängigkeits-Graph is ein Baum

• Angular benötigt nur eine einzige Iteration („digest“) zum Abgleich des Baumes

Page 14

26.09.2016

8

Property-Binding

Page 15

model

item item

{{ item.title }} {{ item.title }}

[http://victorsavkin.com/post/110170125256/change-detection-in-angular-2]

Event-Bindings (One-Way, Bottom/Up)

Page 16

{{ item.title }} {{ item.title }}

Event-Handler

Event-Handler

26.09.2016

9

Event-Bindings (One-Way, Bottom/Up)

• Kein Digest nötig

• Event-Handler == Callbacks

• Aber: Events können Anwendungszustand verändern Digest um Property-Bindings zu aktualisieren

Page 17

Property- und Event-Bindings

Page 18

Property-Bindings

ausführen

Event-Handler warden

ausgeführt

Ereignis tritt ein

Anwendung ist bereit!

Alle Handler ausgeführt

Properties gebunden

26.09.2016

10

Bindings definieren

Page 19

View

Page 20

<button (click)="search()" [disabled]="!from || !to">Search</button>

<table>

<tr *ngFor="let flight of flights">

<td>{{flight.id}}</td>

<td>{{flight.date}}</td>

<td>{{flight.from}}</td>

<td>{{flight.to}}</td>

<td><a href="#" (click)="selectFlight(flight)">Select</a></td>

</tr>

</table>

<td [text-content]="flight.id"></td>

26.09.2016

11

Recap

• Property-Binding: One-Way; Top/Down

• Event-Binding: One-Way; Bottom/Up

• Two-Way-Binding?

• Two-Way = Property-Binding + Event-Binding

Page 21

Property- und Event-Bindings kombinieren

Page 22

<input [ngModel]="from" (ngModelChange)="updateFrom($event)">

updateFrom(newValue) {

this.from = newValue;

}

26.09.2016

12

Property- und Event-Bindings kombinieren

Page 23

<input [ngModel]="from" (ngModelChange)="from = $event">

Syntax-Zucker für Two-Way-Binding

Page 24

<input [(ngModel)]="from">

26.09.2016

13

Vorteile

• Performance

• Events: Flexibilität

• Syntaxzucker: Einfache Nutzung

Page 25

DEMO: Two-Way-Binding

Page 26

26.09.2016

14

Beispiel: flight-card

Page 27

Using flight-card

Page 28

<div *ngFor="let f of flights">

<flight-card [item]="f"

[selectedItem]="selectedFlight"

(selectedItemChange)="selectedFlight = $event">

</flight-card>

</div>

26.09.2016

15

flug-card

Page 29

flug-carditem

selectedItem

>

> > selectedItemChange

flug

selectedFlug

DEMO

26.09.2016

16

Performance-Tuning mit Immutables and Observables

Angular traversiert standardmäßig den gesamten Komponenten-Baum

flights

flight flight

{{ flight.id }} {{ flight.id }}

FlightSearch

Card Card

26.09.2016

17

Immutables

• Unveränderbare Objekte

• Wenn sich repräsentierte Daten ändern: Neues Objekt erzeugen

• Man kann einfach herausfinden, ob sich etwas geändert hat• oldObject == newObject

• Mit oder ohne Bibliotheken möglich (wie immutable.js)

Immutables

const ONE_MINUTE = 1000 * 60;

let oldFlights = this.flights;

let oldFlight = oldFlights[0]; // Flight to change!

let oldFlightDate = new Date(oldFlight.date); // Date to change

26.09.2016

18

Immutables

let newFlightDate = new Date(oldFlightDate.getTime() + ONE_MINUTE * 15);

let newFlight = {

id: oldFlight.id,

from: oldFlight.from,

to: oldFlight.to,

date: newFlightDate.toISOString()

};

let newFlights = [

newFlight,

...oldFlights.slice(1, this.flights.length)

];

this.flights = newFlights;

Auf Änderungen prüfen

console.debug("Array: " + (oldFlights == newFlights)); // false

console.debug("#0: " + (oldFlights[0] == newFlights[0])); // false

console.debug("#1: " + (oldFlights[1] == newFlights[1])); // true

26.09.2016

19

Immutables und Angular 2

• Daten fließen top/down

• Modus für Optimierung: Jedes @Input-Binding einer Komponente ist immutable

• Vereinfacht Prüfung auf Änderung

• Wenn sich kein Input einer Komponente geändert hat• Komponente inkl. aller Sub-Komponenten auslassen

Immutables und Angular

flights

flight flight

{{ flight.id }} {{ flight.id }}

FlightSearch

Card Card

Änderung

26.09.2016

20

Optimierung aktivieren

@Component({[…]changeDetection: ChangeDetectionStrategy.OnPush

})export class FlightCard {

[…]@Input flight;

}

DEMO

26.09.2016

21

Observables mit OnPush

Page 41

flights

flight$ flight$

{{ flight$.id }} {{ flight$.id }}

FlightSearch

Card Card

Change

Observables mit OnPush

Page 42

flights$

flight flight

{{ flight.id }} {{ flight.id }}

FlightSearch

Card

Change

Card

26.09.2016

22

Observable binden

<flight-card

[item]="flight | async" […]>

</flight-card>

Nicht „Alles-oder-Nichts“

• Optimierungen mit Immutables und Observables funktionieren nicht nach dem „Alles-oder-Nichts“-Prinzip

• Sie können bei Bedarf genutzt werden

26.09.2016

23

Formulare

Template-driven Forms<form>

<input type="text" name="von"

[(ngModel)]="von">

</form>

26.09.2016

24

Reaktive Formulareexport class FlugSuchenComponent {

filter: FormGroup;

constructor(flightService: FlightService, fb: FormBuilder) {

[…]

this.filter = fb.group({

von: ['Graz', Validators.required],

nach: ['Hamburg', Validators.required]

});

[…]

}

searchFlights() {

var filter = this.filter.value; […]

}

}

Reaktive Formulare

Page 48

<form [formGroup]="filter">

<input id="from" formControlName="von" type="text">

<div *ngIf="!filter.controls.von.valid">…Error…</div>

[…]

</form>

26.09.2016

25

DEMO

Fazit

• Property-Bindings: Top/Down, One-Way

• Event-Bindings: Bottom/Up, One-Way

• 2-Way-Bindings: Property-Binding + Event-Binding

• Architektur: „Fast by default“

• Wer mehr Performance benötigt: Immutables und Observables

• Template-driven Forms vs. Reactive Forms

26.09.2016

26

Kontakt

[mail] [email protected]

[web] SOFTWAREarchitekt.at

[twitter] ManfredSteyer