Single Page Applications mit AngularJS, Teil 2: Konzepte näher betrachtet

Seite 2: Filter und Dienste

Inhaltsverzeichnis

Nach dem Start der Anwendung werden die erwarteten Namen in den einzelnen Textfeldern angezeigt. Zwar befinden sich weder die Eigenschaft name noch person.name im Scope von ng-repeat, allerdings sucht JavaScript, nachdem es nicht fĂĽndig wurde, im ĂĽbergeordneten Scope weiter.

Ändert der Benutzer jedoch den Namen des ersten div-Elements mit ng-repeat, richtet AngularJS im Scope, den die Direktive für das jeweilige Projekt erzeugt hat, eine Eigenschaft name mit dem neuen Wert ein. Somit wirkt sich die Änderung nicht auf die Stellen aus, die ebenfalls mit name verknüpft sind.

Mehr Infos

Zugriffsregelung

Jedes Scope-Objekt bietet mit den Eigenschaften $parent und $root Zugriff auf den ĂĽbergeordneten Scope sowie auf den Root-Scope.

Ändert der Benutzer hingegen den Namen in der zweiten Textbox, sucht AngularJS nach einer Eigenschaft person und wird im Scope des Controllers fündig. Darauf aktualisiert AngularJS die Eigenschaft name des Objekts, und die Änderung wirkt sich auf alle Stellen aus, die mit der Eigenschaft verknüpft sind.

Neben der Möglichkeit, einen Scope zu schaffen, der mit dem übergeordneten über die Prototypen-Kette in Beziehung steht, haben Direktiven auch die Option, neue, sogenannte isolierte Scopes zu erstellen. Über sie lässt sich nicht oder nur eingeschränkt auf übergeordnete Scopes zugreifen.

Zum Modifizieren von Ausgaben stellt AngularJS dem Entwickler sogenannte Filter zur Verfügung. Damit lassen sich die darzustellenden Informationen zum Beispiel formatieren, filtern oder sortieren. Um einen Filter auf eine zu bindende Eigenschaft anzuwenden, hängt der Entwickler eine Pipe gefolgt vom Namen des Filters an:

<td>{{p.Geburtsdatum | date:'shortDate' }}</td>

Falls der Filter Parameter erwartet, sind sie durch jeweils einen Doppelpunkt getrennt anzuhängen. Ein Filter mit drei Parametern ließe sich somit wie folgt verwenden:

{{ eigenschaft | filter:param1:param2:param3 }}

Das Ergebnis eines Filters kann man als Eingabe für ein weiteres verwenden. Dazu hängt der Entwickler an den Ausdruck erneut eine Pipe, gefolgt vom Filteraufruf:

{{ eigenschaft | filter1:param1:param2:param3 | filter2:param }}

Wie der Name des weiter oben gezeigten Filters vermuten lässt, formatiert es ein Datum. Der Parameter gibt Aufschluss über das Format des Datums. Der hier verwendete Wert shortDate verwendet eine kompakte Darstellung ohne Ausgabe der Uhrzeit. Im Lieferumfang des Frameworks befinden sich im Ordner i18n zahlreiche Dateien, die Formate einzelner Kulturen enthalten. Der Begriff Kultur ist dabei als Kombination von Sprache und Region zu verstehen. Beispiele dafür sind Deutsch/Deutschland (de-DE), Deutsch/Österreich (de-AT) oder Englisch/Großbritannien (en-GB).

Neben dem hier gezeigten Filter date bringt AngularJS einige weitere, die zum Beispiel das Formatieren von Zahlen oder das Sortieren von Arrays erlauben (siehe Dokumentation).

Services stellen in der von AngularJS bereitgestellten Infrastruktur wiederverwendbare und austauschbare Komponenten dar. Durch die Austauschbarkeit kann der Entwickler sie im Zuge eines Unit-Tests durch ein Mock-Objekt ersetzen. Dies ermöglicht ihm ein isoliertes Testen des adressierten Programmteils. So etwas ist unter anderem dann interessant, wenn der durch einen Mock ersetzte Service Ergebnisse liefert, die von Aufruf zu Aufruf variieren, weil sie zum Beispiel von der Zeit oder von externen Daten abhängig sind.

Um einen eigenen Service bereitzustellen, kann der Entwickler, die Funktion factory des jeweiligen Moduls heranziehen, wie im folgenden Codeausschnitt gezeigt. Der erste Parameter repräsentiert den Namen des Services, beim zweiten handelt es sich um ein Array, analog zur Deklaration eines Controllers. Der letzte Eintrag dieses Arrays ist eine Funktion, welche die gewünschte Service-Instanz erzeugt und zurückgibt. Die anderen Einträge des Arrays beinhalten die Namen der Services, die in die Funktion zu injizieren sind.

var app = angular.module("Flug",[]); 
[...]

app.factory("flugService", ["$http", "$q", function ($http, $q) {

return {

load: function (params) {

var deferred = $q.defer();

$http.get("/api/flug", { params: params }).then(function
(result) {
deferred.resolve(result.data);
}).catch(function (reason) {
deferred.reject(reason);
});

return deferred.promise;
}
}

}]);

Statt des Arrays könnte auch nur die Funktion übergeben werden. In diesem Fall schließt AngularJS aufgrund der Namen der Parameter auf die zu injizierenden Services. Wie bereits im ersten Teil der Artikelserie beschrieben, kommt es beim gemeinsamen Einsatz dieser etwas kürzeren Schreibweise und Minification zu Problemen, da hierbei in der Regel die ursprünglichen Parameternamen durch kürzere ersetzt werden. Möchte der Entwickler also Minification anwenden, muss er wie oben gezeigt auf das Array zugreifen.