GEDOPLAN

[deprecated]Angular 2 – Konverter ($parsers and $formatters)

Alle

Der folgende Abschnitt ist veraltet!In der aktuellen Version ist folgendes Vorgehen zu verwenden:

https://javaeeblog.wordpress.com/?p=4409

Angular 2 steht in den Startlöchern bereit, wenn auch erst in einer frühen Beta-Phase. Zeit genug also sich mit der neuen Welt von Anuglar JS vertraut zu machen. Bei den ersten Schritten stolpert man sehr schnell über die Frage: Wie findet eine Konvertierung von Daten zwischen View und Modell statt? In Angular1 standen uns hierfür $formatters und $parsers zur Verfügung, in Angular2 gibt es dazu bisher kein offizielles Konzept (siehe GitHub ). Aber werfen wir einen Blick auf die Möglichkeiten die sich uns heute schon bieten…

 

Das typische Binding einer Eingabe Komponente in Angular 2 sieht bekanntlich so aus:

<input id="datefield" [(ngModel)]="recordService.record.startTime" />

Durch die doppelte Klammerung („[(….)]“, alternativ: „onbind-ngModel“) zusammen mit der „ngModel“-Direktive führen wir an dieser Stelle ein Two-Way-Binding ein mit dessen Hilfe die Werte unseres Models in der View angezeigt und Änderungen zurück gespielt werden. Nutzen wir dieses Vorgehen auch für ein Datenfeld vom Typ „Date“ führt dies dazu, dass wir in der Anzeige die unansehnliche String Repräsentation eines Date-Objektes finden, das bei Änderungen zu allem Überfluss auch noch als String zurück ins Model geschrieben wird. Ein Converter / Parser muss also her. $parsers und $formatters aus Angular 1 haben (bisher?) ihren Weg noch nicht in den Version 2. geschafft, dennoch gibt es mit den bestehenden Mittel die Möglichkeit eine solche Funktion zu implementieren: eine eigene Direktive:

(hier einmal die gesamte Implementierung in TypeScript, im Folgenden werde wir auf die einzelnen Punkte eingehen)

import {Directive, Renderer, ElementRef} from 'angular2/core'
import {NgModel, DefaultValueAccessor} from 'angular2/common'

@Directive({
selector: '[tsdate]',
host: {
    '(change)': 'onChanges($event.target.value)'
}
})
export class DateDirective extends DefaultValueAccessor {

constructor(private model: NgModel, private el: ElementRef, private renderer: Renderer) {
    super(renderer, el);
    model.valueAccessor = this;
}

writeValue(obj: Date): void {
    if (obj) {
        super.writeValue(this.formatDate(obj));
    }
}

onChanges(value: string) {
    this.onChange(this.parseDate(value));
}

formatDate(inputDate: Date): string {
    // Datum formatieren
    return ...
}

parseDate(inputString: string): Date {
 // Datum parsen
 return ...Date...
}
}

Mittels des TypeScript Decorators „Directive“ erzeugen wir hier eine Direktive die später an HTML Elemente angehängt werden kann. Über welche Property dies geschieht legen wir durch das selector Attribut fest: selector: ‚[tsdate]‘, Verwendung: . Als weiteren Schritt wollen wir geänderte Eingaben des Textfeldes auf dem die Direktive verwendet werden soll mit einer entsprechenden Methode versehen um darauf zu reagieren. Mit Hilfe des „host“ Attributes registrieren wir uns auf das entsprechende „change“-Event des übergeordneten HTML Elements (in unserem Fall: „input“) um zusammen mit dem Wert des Textfeldes als Parameter eine unserer Methoden auf zu rufen.

Die eigentliche Implementierung unserer Logik findet in der anschließend deklarierten Klasse statt:

export class DateDirective extends DefaultValueAccessor

Dabei erben wir von der Angular zur Verfügung gestellten Klasse: DefaultValueAccessor (implements ControlValueAccessor). Diese Klasse wird von der NgModel-Direktive verwendet um Änderungen ins Model zurück zu schreiben und auf Eingaben des Benutzers zu reagieren.

constructor(private model: NgModel, private el: ElementRef, private renderer: Renderer) {
    super(renderer, el);
    model.valueAccessor = this;
}

Innerhalb des Konstruktors lassen wir uns unter anderem das NgModel injizieren mit dessen Hilfe wir das Ein- und Ausgabeverhalten der Direktive anpassen werden. Dazu ändern wir den valueAccessor auf die aktuelle Klasse um die von uns benötigten Methoden zu überschreiben und nach Bedarf an zu passen.

Die beiden entscheidenen Methoden die wir  dazu nutzen sind:

writeValue(obj: Date): void

Die „writeValue“ Methode wird aufgerufen um einen Wert aus dem Model in die View zu übertragen. An dieser Stelle greifen wir ein und nehmen das Date-Objekt aus dem Model um es in eine für uns angenehme String-Repräsentation zu bringen. Das eigentliche setzen des value-Attributes des Textfeldes überlassen wir dann der Standard Implementierung.

onChanges(value: string)

Wie in der Konfiguration angegeben wird diese Methode bei Änderungen des Textfeldes aufgerufen und mit dem geänderten Wert versorgt. An dieser Stelle führen wir die Umwandlung des Strings in ein echtes JavaScript Datum durch, um zum Abschluss erneut die Standard Implementierung dafür zu bemühen diesen Wert ans Model zu übertragen

Wie wir sehen konnten besteht auch mit den in der Beta-Version zur Verfügung gestellten Mitteln eine recht übersichtliche Möglichkeit einen Konverter/Parser zu implementieren. Ob dieses Vorgehen in dieser Form auch in Zukunft Verwendung findet oder es eine ergänzendes Konzept in Angular 2 geben wird muss sich zeigen.

Das Beispiel findet sich noch einmal hier in seiner gesamten Form: github

Autor

Diesen Artikel teilen

LinkedIn
Xing

Gibt es noch Fragen?

Fragen beantworten wir sehr gerne! Schreibe uns einfach per Kontaktformular.

Schulungen mit der selben Kategorie:

Blogkategorie: Alle
Es wurden keine Ergebnisse gefunden.

weitere Artikel

Kontakt

Brauchen Sie eine individuelle IT-Schulung, eine fundierte Beratung oder eine individuelle Softwareentwicklung? Dann sind Sie hier genau richtig!

Tim Neumann

Geschäftsleitung

GEDOPLAN GmbH
Stieghorster Straße 60
33605 Bielefeld

GEDOPLAN GmbH
Kantstraße 164
10623 Berlin

    Kontakt

    Tim Neumann

    Geschäftsleitung

    GEDOPLAN GmbH
    Stieghorster Straße 60
    33605 Bielefeld

    GEDOPLAN GmbH
    Kantstraße 164
    10623 Berlin

    Brauchen Sie eine individuelle IT-Schulung, eine fundierte Beratung oder eine individuelle Softwareentwicklung? Dann sind Sie hier genau richtig!