Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Angular 2 Workshop at w-jax 2016, Munich, November 2016

Angular 2 Workshop at w-jax 2016, Munich, November 2016

Manfred Steyer

November 07, 2016
Tweet

More Decks by Manfred Steyer

Other Decks in Programming

Transcript

  1. Über mich …  Manfred Steyer  SOFTWAREarchitekt.at  Trainer

    & Consultant  GDE & MVP  Focus: Angular 2 Page  2 ManfredSteyer
  2. Component Controller Page  45 @Component({ selector: 'flug-suchen', templateUrl: 'flug-suchen.html'

    }) export class FlugSuchenComponent { von: string; nach: string; fluege: Array<Flug>; constructor(http: Http) { } search() { [...] } select(flug) { [...] } }
  3. Template Page  46 <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>
  4. Template Page  47 <input bindon-ngModel="von"> <input bindon-ngModel="nach"> <button bind-disabled="!von

    || !nach" on-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>
  5. AppComponent Page  51 <nav class="navbar navbar-default navbar-fixed-top"> <!-- Menü

    --> </nav> <div class="container"> <flug-suchen></flug-suchen> </div>
  6. Module Page  52 Module X Module Y AppModule AppComponent

    FlugSuchenComponent … … import import Root-Component (AppComponent)
  7. AppModule Page  53 @NgModule({ imports: [ BrowserModule, HttpModule, FormsModule

    ], declarations: [ AppComponent, FlugSuchenComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }
  8. Möglichkeiten für Projektstart Page  70 • Aufwändig • Viele

    Freiheiten Manuell • cli.angular.io • Einfach • Weniger Freiheiten CLI • Einfach • Viele Freiheiten Seed- Projekte
  9. Dateien und Ordner Page  72 • Quellcode (TypeScript) app

    • Kompilate dist • Bibliotheken node_modules • Typdeklarationen für TypeScript typings • Verweis auf Bibliotheken und Skripte package.json • Verweis auf Typdeklarationen typings.json • Konfiguration für TypeScript-Compiler tsconfig.json • Konfiguration für Bundler (webpack) webpack.config.js • Startdatei index.html
  10. Webpack Page  73 File A File B File C

    File D File E Entry Point Bundle Bundle Loader (z.B. .ts  .js)
  11. package.json Page  74 { "dependencies": { "@angular/common": "2.0.0-rc.1", […]

    }, "devDependencies": { "typings": "^0.7.9", "webpack": "^1.12.9", "webpack-dev-server": "^1.14.0", […] }, […] }
  12. package.json Page  75 { "dependencies": { "@angular/common": "2.0.0-rc.1", […]

    }, "devDependencies": { "typings": "^0.7.9", "webpack": "^1.12.9", "webpack-dev-server": "^1.14.0", […] }, "scripts": { "postinstall": "typings install", "webpack": "webpack", "start": "webpack-dev-server", }, […] }
  13. package.json Page  76 { "dependencies": { "@angular/common": "2.0.0-rc.1", […]

    }, "devDependencies": { "typings": "^0.7.9", "webpack": "^1.12.9", "webpack-dev-server": "^1.14.0", […] }, "scripts": { "postinstall": "typings install", "webpack": "webpack" "start": "webpack-dev-server", }, […] }
  14. package.json Page  77 { "dependencies": { "@angular/common": "2.0.0-rc.1", […]

    }, "devDependencies": { "typings": "^0.7.9", "webpack": "^1.12.9", "webpack-dev-server": "^1.14.0", […] }, "scripts": { "postinstall": "typings install", "webpack": "webpack" "start": "webpack-dev-server", }, […] } npm install npm start npm run webpack
  15. Constructor Injection Page  85 @Component({ selector: 'flug-suchen', templateUrl: 'flug-suchen.html'

    }) export class FlugSuchenComponent { von: string; nach: string; fluege: Array<Flug>; constructor(flugService: FlugService) { } flugSuchen() { [...] } selectFlug(flug) { [...] } }
  16. Service Page  87 @Injectable() export class FlugService { […]

    } Services sind Singletons (in ihrem "Scope")
  17. Funktionsweise  Provider bindet Services an Token  Andere Services

    und Komponenten fordern für Token eine Implementierung an Page  88
  18. Token  Fast alles kann ein Token sein!  Häufig:

    Standard-Implementierung des Services  Abstrakte (Basis)-Klasse  Konstante  NICHT: Interface Page  89
  19. Service an Token binden (global) Page  94 @NgModule({ imports:

    [ BrowserModule, HttpModule, FormsModule ], declarations: [ AppComponent, FlugSuchenComponent ], providers: [ { provide: FlugService, useClass: AdvancedFlugService } ], bootstrap: [ AppComponent ] }) export class AppModule { }
  20. Service an Token binden (global) Page  95 @NgModule({ imports:

    [ BrowserModule, HttpModule, FormsModule ], declarations: [ AppComponent, FlugSuchenComponent ], providers: [ { provide: FlugService, useClass: FlugService } ], bootstrap: [ AppComponent ] }) export class AppModule { } Modul richtet Provider global ein!
  21. Service an Token binden (global) Page  96 @NgModule({ imports:

    [ BrowserModule, HttpModule, FormsModule ], declarations: [ AppComponent, FlugSuchenComponent ], providers: [ FlugService ], bootstrap: [ AppComponent ] }) export class AppModule { }
  22. Service an Token binden (pro Komponente) Page  97 @Component({

    selector: 'flug-suchen', templateUrl: 'app/flug-buchen/flug-buchen.html', providers: [{ provide: FlugService, useClass: FlugService}] }) export class FlugSuchenComponent { […] } Gilt nur für aktuelle Komponente und darunter!
  23. Service an Token binden (pro Komponente) Page  98 @Component({

    selector: 'flug-suchen', templateUrl: 'app/flug-buchen/flug-buchen.html', providers: [FlugService] }) export class FlugSuchenComponent { […] }
  24. Service anfordern Page  100 @Component({ selector: 'flug-suchen', templateUrl: 'flug-suchen.html',

    }) export class FlugSuchenComponent { von: string; nach: string; fluege: Array<Flug>; constructor(flugService: FlugService) { } flugSuchen() { [...] } selectFlug(flug) { [...] } } Angefordertes Token
  25. Service anfordern Page  101 @Component({ selector: 'flug-suchen', templateUrl: 'flug-suchen.html'

    }) export class FlugSuchenComponent { von: string; nach: string; fluege: Array<Flug>; constructor(@Inject(FlugService) flugService) { } flugSuchen() { [...] } selectFlug(flug) { [...] } }
  26. Idee  Daten im Zuge der Bindung transformieren ("formatieren") 

    Grammatik:  {{ f.von | ort }}  {{ f.von | ort:'short' }}  {{ f.von | ort:'short':'en' }}  {{ f.von | ort:'short':'en' | uppercase }} Page  106
  27. Pure Pipes  Ausgabe hängt nur von Eingabeparametern ab 

    Konsequenz: Performanceoptimierungen möglich Page  108
  28. Deklaration einer Pipe Page  109 import {Pipe} from '@angular/core';

    @Pipe({ name: 'ort', pure: true }) export class OrtPipe implements PipeTransform { transform(value: any, ...args: Array<any>): any { […] return […]; } }
  29. AppModule Page  110 @NgModule({ imports: [ BrowserModule, HttpModule, FormsModule

    ], declarations: [ AppComponent, FlugSuchenComponent, OrtPipe ], bootstrap: [ AppComponent ] }) export class AppModule { }
  30. Komponenten-Baum in Angular 2 Page  115 Komponente für App

    Komponente (z. B. Liste) Komponente (z. B. Eintrag) Komponente (z. B. Eintrag)
  31. Regeln für Property-Bindings  Eine Komponente hängt nur von ihren

    eigenen Daten (und indirekt von denen des Parents) ab  Eine Komponente hängt nicht von Daten ihrer Kinder ab!  Abhängigkeits-Graph ist ein Baum  Angular benötigt nur einen Digest um Baum mit GUI abzugleichen Page  117
  32. Property-Binding Page  118 model item item {{ item.title }}

    {{ item.title }} [http://victorsavkin.com/post/110170125256/change-detection-in-angular-2]
  33. Event-Bindings (One-Way, Bottom/Up) Kein Digest um Events zu versenden Aber:

    Events können Daten ändern  Property Binding Page  124
  34. Property- und Event-Bindings Page  126 Property-Binding ausführen Event-Handler ausführen

    Ereignis tritt ein App ist bereit Alle Handler ausgeführt Properties gebunden
  35. View Page  129 <button [disabled]="!von || !nach" (click)="search()"> 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>
  36. Komponenten und Direktiven Direktiven Fügen Verhalten zu Elementen hinzu Referenzieren

    Element über Selektor Beispiele: ngModel, ngStyle, ngClass Komponenten Direktiven mit Template Können weitere Direktiven haben Page  139
  37. Beispiel: flug-card in flug-suchen.html Page  143 <div *ngFor="let f

    of fluege"> <flug-card [item]="f" [selected]="f == selectedFlug" (selectedChange)="select(f)"> </flug-card> </div>
  38. Beispiel: flug-card @Component({ selector: 'flug-card', templateUrl: 'app/flug-card/flug-card.html' }) export class

    FlugCard { @Input() item: Flug; @Input() selected: boolean; @Output() selectedChange = new EventEmitter(); select() { this.selectedChange.emit(true); } }
  39. Template <div style="padding:20px;" [ngStyle]="{'background-color': (selected) ? 'orange' : 'lightsteelblue' }"

    > <h2>{{item.abflugort}} - {{item.zielort}}</h2> <p>Flugnr. #{{item.id}}</p> <p>Datum: {{item.datum}}</p> <p> <button class="btn btn-default" (click)="select()"> Auswählen </button> </p> </div>
  40. Komponente registrieren Page  151 @NgModule({ imports: [ CommonModule, FormsModule,

    SharedModule ], declarations: [ FlugSuchenComponent, FlugCardComponent ], providers: [ FlugService ], exports: [ FlugSuchenComponent ] }) export class FlugModule { }
  41. I18N  Angular Compiler  Extrahiert Texte aus Templates in

    Sprachfiles  Kompiliert Sprachfiles (XML) zurück in Anwendung  Kompilierung beim Start (JIT) oder Build (AOT)  https://angular.io/docs/ts/latest/cookbook/i18n.html  Sprach kann im Betrieb nicht geändert werden  Hohe Performance Page  153
  42. I18N  Angular 2 Translate  Community Lösung  Leichtgewichtig,

    erweiterbar  https://github.com/ocombe/ng2-translate  Migration von defacto-Standard für AngularJS 1.x  JSON-basierte Dateien  Sprache kann während der Laufzeit geändert werden  Nicht so performant wie Angular Compiler I18N  Keine Möglichkeit, Texte zu extrahieren Page  154
  43. Nutzung Page  158 @Component({ selector: 'my-component', […] }) export

    class Component implements OnChange, OnInit { @Input() someData; ngOnInit() { […] } ngOnChange() { […] } } <my-component [someData]="myVariable"> </my-component>
  44. Motivation  SPAs bestehen aus einer Seite  Innerhalb dieser

    werden Bereiche ein- und ausgeblendet --> "Logische Seiten", Routen  Url sollte auf Route hinweisen  Bookmarks  Back-Button  Router unterstützen hierbei Page  160
  45. Routing unter AngularJS Page  167 Logo + Menü Menü

    2 Fußzeile SPA Passagier- Komponente /FlugDemo#passagier
  46. Routen via History API  /FlugDemo/passagier  Gesamte Url wird

    zum Server gesendet  Server antwortet mit SPA  Server kann erste Ansicht "vorrendern"  Performance, SEO, …  SPA informiert Browser über Grenze zwischen physischer und logischer Url Page  173
  47. Vorbereitung  ES6/TypeScript-Modul: @angular/router  (Alte Impl.: @angular/router-deprecated, vormals: angular2/router)

     Angular 2 Modul: RouterModule  Festlegen der Grenze zwischen URL und Route bei History API:  <base href="/">  Oder: Token APP_BASE_HREF (@angular/common) Page  180
  48. Konfiguration Page  181 const APP_ROUTES: Routes = [ {

    path: 'home', component: HomeComponent }, { path: 'flug-suchen', component: FlugSuchenComponent } }
  49. Konfiguration Page  182 const APP_ROUTES: Routes = [ {

    path: '', redirectTo: 'home', pathMatch: 'full' }, { path: 'home', component: HomeComponent }, { path: 'flug-suchen', component: FlugSuchenComponent } }
  50. Konfiguration Page  183 export const AppRoutesModule = RouterModule.forRoot(ROUTE_CONFIG); //

    app.module.ts @NgModule({ imports: [ BrowserModule, HttpModule, FormsModule, AppRoutesModule ], […] }) export class AppModule { } Für Root-Module Für Feature-Module: forChild
  51. Konfiguration Page  189 const APP_ROUTES: Routes = [ […]

    { path: 'flug-suchen', component: FlugSuchenComponent }, { path: 'flug-edit/:id', component: FlugEditComponent } }
  52. Parameter auslesen Page  190 export class FlugEditComponent { public

    id: string; constructor( private route: ActivatedRoute) { route.params.subscribe( p => { this.id = p['id']; […] } ); } […] }