Upload
sebastian-springer
View
504
Download
0
Embed Size (px)
Citation preview
@basti_springer
Agenda• Komponenten
• Module
• Datenfluß
• Direktiven
• Services
• Pipes
• Routing
Wo soll ich denn Anfangen?
Angular CLI
Angular CLI
Angular CLI
Angular CLI
Installiert alle benötigten Abhängigkeiten. Legt eine Projektstruktur an.
Stellt eine Entwicklungsumgebung zur Verfügung.
Kommandos zum Scaffolding. Kommandos zum Bauen der Applikation.
Angular CLI
ng serve: liefert die Applikation auf localhost:4200 aus Proxykonfiguration für Backend möglich.
ng build: baut die Applikation für den Produktivbetrieb
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
@NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, HttpModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
Module
declarations: Komponenten und Direktiven imports: Weitere Module importieren providers: Global im Modul verfügbare Services bootstrap: Die Bootstrapping Komponente angeben
Komponenten
Grundbaustein einer Applikation. Sind für die Anzeige von Informationen und die Behandlung
von Benutzereingaben zuständig.
Komponenten
Komponenten
Komponentenimport { Component, OnInit } from '@angular/core';
@Component({ selector: 'app-add-list', templateUrl: './add-list.component.html', styleUrls: ['./add-list.component.css'] }) export class AddListComponent implements OnInit {
constructor() { }
ngOnInit() { }
}
Komponenten
Eine Komponente pro Datei.
Pro Komponente ein Verzeichnis.
Dateiname: <Bezeichnung>.component.ts add-list.component.ts
Komponenten
Selektoren prefixen - z.B. mit Applikations-Shortcut.
Komponenten an Elemente binden. Attribute, Klassen und IDs sind zwar möglich, sollte man aber nicht nutzen.
Templates
import { Component } from '@angular/core';
@Component({ selector: 'add-list', template: ‘<div>Hello World</div>‘, }) export class AddListComponent { }
Bei sehr kleinen Komponenten können die Templates inline erzeugt werden. Im Normalfall liegen sie aber in einer eigenen
Datei.
Styles
Angular erlaubt es Styles pro Komponente zu erzeugen. Diese gelten dann nur für die Komponente.
Styles können auch inline oder in einer separaten Datei geschrieben werden
Stylesul { list-style: none; }
Interpolation
Darstellen der Informationen aus der Komponenten-Klasse.
Ändert sich der Wert in der Komponente, wird er in das Template synchronisiert.
Darstellung von Informationen
export class AddListComponent implements OnInit {
private headline = 'Addresslist'; private addresses: Address[];
constructor() { this.addresses = [ {name: 'Peter', street: 'Kirchplatz 2', place: '20095 Hamburg'}, {name: 'Paul', street: 'Sonnenstraße 14', place: '80331 München'} ]; }
ngOnInit() { } }
Lifecycle Hooks
Darstellung von Informationen
Wir arbeiten mit Typescript, also können wir auch Klassen für unsere Datenstrukturen erstellen.
export class Address { constructor( public name: string, public street: string, public place: string, public rating: number) {} }
Direktiven
Struktur Direktiven
verändern die Struktur der View.
ngIf, ngFor
Attribut Direktiven
beeinflussen das Verhalten von Elementen
ngStyle
Die Angular-eigenen Direktiven werden über das BrowserModule zur Verfügung gestellt.
Darstellung von Informationen
<ul> <li *ngFor="let address of addresses"> {{address.name}} - {{address.street}} - {{address.place}} </li> </ul>
DirektivenDer * bei Strukturdirektiven ist eine Shortcut-Form für die
Template-Schreibweise.
Strukturdirektiven nutzen intern HTML5 Template-Tags.
<p *ngIf="condition"> Hello World </p>
<template [ngIf]="condition"> <p> Hello World </p> </template>
Data-BindingTyp Syntax
Interpolation {{value}}
Property-Binding [src]=“logo”
Event-Binding (click)=“hello()”
2 Way Data-Binding [(ng-model)]=“myValue”
Property Binding<img [src]="logo" />
Eigenschaften von Elementen mit dynamischen Werten setzen.
Event-Binding
<button type="button" name="button" (click)="hello($event)">Click me</button>
Die Methode hello der Komponenten-Klasse wird beim Click-Event ausgeführt.
Das $event-Objekt enthält alle Informationen über das Event.
Komponentenhierarchie
Eine Angular-Applikation besteht in den meisten Fällen aus einer Hierarchie von Komponenten.
Jede Komponente kann eine oder mehrere Kindkomponenten beinhalten.
Komponentenhierarchie
Eine Kindkomponente wird erstellt, sobald die Elternkomponente zu umfangreich wird,
zu viele Dinge parallel tut oder wenn Elemente an anderen Stellen wiederverwendet
werden sollen.
Komponentenhierarchie
import { Component, OnInit } from '@angular/core';
@Component({ selector: 'app-rating', templateUrl: './rating.component.html', styleUrls: ['./rating.component.css'] }) export class RatingComponent implements OnInit {
constructor() { }
ngOnInit() { }
}
Die Kindkomponente
Komponentenhierarchie
<h1>{{headline}}</h1>
<ul> <li *ngFor="let address of addresses"> {{address.name}} - {{address.street}} - {{address.place}} <app-rating></app-rating> </li> </ul>
Im Template der Elternkomponente:
👫 → 👶
Eltern → Kind
Wie kommen die Informationen der Elternkomponente in die Kindkomponente?
Eltern → Kind<app-rating [item]="address"></app-rating>
@Component({ selector: 'app-rating', templateUrl: './app-rating.component.html', styleUrls: ['./app-rating.component.css'] }) export class AppRatingComponent implements OnInit {
@Input() item: RatingItem;
constructor() { }
ngOnInit() { } }
👶 ! 👫
Kind → Eltern
Da die Informationen per Referenz an die Kinder übergeben werden, können diese die Informationen verändern und die
Elternkomponente erhält die Änderungen ebenfalls.
Kind → Eltern
export class AppRatingComponent {
@Input() item: RatingItem;
constructor() { }
rate(value) { this.item.rating = value; } }
Kind → Eltern
Die bessere Lösung: Eventbinding nach außen.
Kind → Eltern
1. Eventemitter in der Kindkomponente implementieren
2. Eventemitter mit dem @Output Decorator kennzeichnen
3. Eventbinding in der Elternkomponente umsetzen
4. Methode zur Behandlung in der Elternkomponente implementieren
Kind → Elternimport { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { RatingItem } from '../shared/rating-item';
@Component({…}) export class AppRatingComponent {
@Input() item: RatingItem; @Output() rating = new EventEmitter();
rate(value) { var copy = Object.assign({}, this.item) copy.rating = value; this.rating.emit(copy); } }
Kind → Eltern
<ul> <li *ngFor="let address of addresses"> {{address.name}} - {{address.street}} - {{address.place}} <app-rating [item]="address" (rating)="rating($event)"></app-rating> </li> </ul>
Kind → Elternimport { Component, OnInit } from '@angular/core';
import { Address } from '../shared/address';
@Component({…}) export class AddListComponent implements OnInit {
private addresses: Address[];
constructor() { this.addresses = […]; }
rating(address: Address) { // save to server console.log('saving'); let index = this.addresses.findIndex((el) => { if (el.name === address.name && el.street === address.street && el.place === address.place) { return true; } return false; }); this.addresses[index] = address; } }
Service
Services werden zur Auslagerung von Logik verwendet.
Sie können Informationen zur Verfügung stellen oder zur Kommunikation verwendet werden.
Service
1. Service erzeugen
2. Im Modul registrieren
3. Per Dependency Injection einbinden
Service$ ng g service converter
import { Injectable } from '@angular/core';
@Injectable() export class ConverterService {
private dolEur = 0.919337342; private eurDol = 1.08774;
dollarToEuro(dollar) { return dollar * this.dolEur; } euroToDollar(euro) { return euro * this.eurDol; } }
Service… import { ConverterService } from './converter.service';
@NgModule({ declarations: […], imports: […], providers: [ ConverterService ], bootstrap: […] }) export class AppModule { }
Service… import { ConverterService } from '../converter.service';
@Component({…}) export class AddListComponent implements OnInit {
… private value: number;
constructor(private converterService: ConverterService) { this.value = this.converterService.dollarToEuro(15); … } }
Serverkommunikationimport { Injectable } from '@angular/core'; import { Address } from './shared/address'; import { Http } from '@angular/http'; import 'rxjs/add/operator/toPromise';
@Injectable() export class AddressService {
constructor(public http: Http) { }
get(id: number): Promise<Address> { return this.http.get('/address/' + id) .toPromise() .then(res => { return res.json() as Address; }); } }
Direktiven
Direktiven
1. Direktive erzeugen
2. Als Declaration im Module registrieren
3. Als Attribut einbinden
Direktiven$ ng g directive unless
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({ selector: '[unless]' })
export class UnlessDirective {
constructor( private templateRef: TemplateRef<any>, private viewContainer: ViewContainerRef ) { }
@Input() set unless(condition: boolean) { if (!condition) { this.viewContainer.createEmbeddedView(this.templateRef); } else { this.viewContainer.clear(); } } }
Direktiven… import { UnlessDirective } from './unless.directive';
@NgModule({ declarations: [ … UnlessDirective ], imports: […], providers: […], bootstrap: […] }) export class AppModule { }
Direktiven
<div *unless="true"> UNLESS TRUE </div>
<div *unless="false"> UNLESS FALSE </div>
Den Stern nicht vergessen, sonst: Error: No provider for TemplateRef!
Pipes
Pipes werden verwendet, um eine Eingabe in eine Ausgabe zu transformieren.
Pipes werden hauptsächlich in Templates eingesetzt.
Pipes können parametrisiert werden: value | pipe : ‘a’: ‘b’
Mehrere Pipes können hintereinander geschaltet werden.
Pipes
1. Pipe erzeugen
2. Pipe im Module, im Abschnitt declarations registrieren
3. Pipe im Template nutzen
Pipes$ ng g pipe converter
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'converter' }) export class ConverterPipe implements PipeTransform {
transform(value: any, what: string): any { let multiplier = 1; … return value * multiplier; } }
Pipes… import { ConverterPipe } from './converter.pipe';
@NgModule({ declarations: [ … ConverterPipe ], imports: […], providers: […], bootstrap: […] }) export class AppModule { }
Pipes
Pipe: {{ 15 | converter : 'dollarToEuro' }}
Pipes
Aus Performancegründen gibt es keine OrderBy- und Filter-Pipes in Angular mehr. Diese müssen entweder über externe
Module eingebunden werden oder selbst implementiert werden.
Pipesimport { Pipe, PipeTransform } from '@angular/core'; import {Todo} from "./todo";
@Pipe({ name: 'filter' }) export class FilterPipe implements PipeTransform {
transform(todos: Todo[], args?: any): Todo[] { if (args === 'all') { return todos; } return todos.filter((todo) => { return todo.status == args }); } }
Forms
Angular bietet zahlreiche Hilfestellungen für die Formularbehandlung.
Forms
1. Forms Modul einbinden
2. Formular erstellen
Formsimport { FormsModule } from '@angular/forms';
@NgModule({ declarations: […], imports: [… FormsModule ], providers: […], bootstrap: [AppComponent] }) export class AppModule { }
FormsState Klassen, wenn
zutreffendKlasse, wenn nicht
zutreffend
Element wurde besucht ng-touched ng-untouched
Wert wurde verändert ng-dirty ng-pristine
Wert ist gültig ng-valid ng-invalid
Forms
<input type="text" name="name" [(ngModel)]="value" #name="ngModel">
{{name.pristine}}
Validatoren
Bestehende Validatoren: required, minlength, maxlength, pattern
Eigene Validatoren können über Direktiven implementiert werden.
Routing
Andreas Hermsdorf / pixelio.de
Routing
Routing wird zur Navigation in Single Page-Applikationen verwendet.
Der Angular Router kann verschiedene Komponenten an bestimmten stellen der Applikation einbinden, je nachdem
welche Applikationsstatus aktiviert wird.
Der Applikationsstatus kann über die URL geändert werden.
Routing
1. base href=“/“ setzen
2. Routermodul einbinden
3. Router-Outlet anlegen
4. Routingkonfiguration erstellen
Routingimport { ModuleWithProviders } from '@angular/core'; import { Routes, RouterModule } from '@angular/router';
const appRoutes: Routes = [ { path: '', redirectTo: 'list', pathMatch: 'full' }, { path: 'list', component: ListComponent }, { path: 'form', component: FormComponent }, { path: 'form/:id', component: FormComponent } ];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
Routing… import { routing } from './app.routing';
@NgModule({ declarations: […], imports: [… routing ], providers: […], bootstrap: [AppComponent] }) export class AppModule { }
Routing
<a routerLink="/form">Neuer Datensatz</a>
Im Template kann mit der routerLink-Direktive navigiert werden.
Routing
import { Component, OnInit } from '@angular/core'; import { Router, NavigationExtras } from '@angular/router';
@Component({…}) export class TodoListComponent implements OnInit {
constructor(private router: Router) { }
private create() { this.router.navigate(['/form']) } }
Im Controller wird über die router.navigate-Methode navigiert.
RoutingZugriff auf Variablen.
{ path: 'form/:id', component: FormComponent }
ngOnInit() { this.route.params.forEach((params: Params) => { let id = +params['id'];
… }); }
3rd Party Module
3rd Party Module
Module von Drittanbietern stellen Komponenten, Direktiven, Pipes und Services zur Verfügung.
Sie können in die Applikation eingebunden und verwendet werden.
3rd Party ModuleAngular Material
1. Installation
2. Einbindung
3. Verwendung
3rd Party Module
npm install --save @angular/material
3rd Party Module
import { MaterialModule } from '@angular/material'; @NgModule({ imports: [MaterialModule.forRoot()], … }) export class AppModule { }
3rd Party Module<md-card> <label> Indeterminate progress-bar <md-progress-bar class="app-progress" mode="indeterminate" aria-label="Indeterminate progress-bar example"></md-progress-bar> </label>
<label> Determinate progress bar - {{progress}}% <md-progress-bar class="app-progress" color="accent" mode="determinate" [value]="progress" aria-label="Determinate progress-bar example"></md-progress-bar> </label> </md-card>
3rd Party Module
progress: number = 0;
constructor() {
setInterval(() => { this.progress = (this.progress + Math.floor(Math.random() * 4) + 1) % 100; }, 200); }
3rd Party Module
Fragen?
Rainer Sturm / pixelio.de