Parsing mit $compile, $interpolate und $parse
angularjs | Sascha Brink • | 5 Minuten
Ziel des Artikels:
Wie AngularJS ein HTML-Template verarbeitet, ist in den Tiefen des Frameworks verborgen. Normalerweise muss man auch nicht wissen, wie es funktioniert. Das ändert sich, wenn man eigene Direktiven zu baut. In diesem Fall kommt man sehr oft in die Situation, Templates oder Variablen selbst kompilieren zu müssen. Dazu braucht man einen der folgenden Services: $compile, $interpolate oder $parse. In diesem Artikel geht es darum, wie sie sich unterscheiden und wie man sie benutzt.
Der typische Anwendungsfall
Ihr habt eine eigene Direktive mit einer link-Funktion. In dieser erstellt ihr manuell eigene Elemente.
.directive('name', function($compile) {
return {
restrict: 'E',
link: function(scope, element) {
element.html('{{name}}');
}
}
});
Fokussiert euren Blick kurz auf die link-Funktion, wo wir ein Element mit dem Inhalt {{name}}
erstellen. Wenn ihr diese Direktive mit <name></name>
im HTML benutzt, wäre das Ergebnis immer {{name}}
.
Da wir aber mit AngularJS arbeiten, wollen wir normalerweise nicht {{name}}
ausgeben, sondern den Inhalt der Variable name
. Dafür brauchen wir in diesem Fall $compile
.
.directive('name', function($compile) {
return {
restrict: 'E',
link: function(scope, element) {
element.html('{{name}}');
$compile(element.contents())(scope);
}
}
});
Kompilieren wir den Inhalt von element
zusätzlich mit $compile
, verhält sich alles wie erwartet. Die Variable name
wird per Two-Way-Databinding automatisch aktualisiert.
Das wäre ein Beispiel für $compile. Gehen wir die drei Services im Folgenden durch.
Die Services $compile, $interpolate, $parse
Das Wichtige zuerst: $compile, $interpolate und $parse folgen einer Hierarchie.
Sehr einfach verständlich mit folgenden Beispielen:
- $compile:
<p>Hallo {{name}}</p>
- $interpolate:
Hallo {{name}}
- $parse:
name
Übersicht:
- $compile bezieht sich auf Zeichenketten mit HTML-Tags. Zwischen den Tags wird
$interpolate
aufgerufen - $interpolate bezieht sich auf Zeichenketten, die Expressions enthalten können. Kommen dabei HTML-Tags vor, wird ein Fehler geworfen.
$parse
wird auf Expressions angewendet. - $parse bezieht sich auf den Inhalt von Expressions
$compile
Ergebnis: jqLite/jQuery-Element
$compile braucht immer einen Tag zum Öffnen und einen zum Schließen. Selbstschließende Tags werfen einen Fehler.
Beispiel:
scope.name = 'Welt';
$compile('<p>Hallo {{name}}</p>')(scope)
// => [p.ng-binding.ng-scope]
$compile
ist der Service, der an oberster Stelle steht. Er unterteilt einen HTML-Tag in einzelne Tokens. Auf den Inhalt eines Tokens wird $interplate
angewendet.
Das Ergebnis von $compile ist ein jqLite/jQuery-Element!
Dieser Service sorgt auch dafür, dass entsprechende Watcher mit $watch
auf dem Scope registriert werden. Deshalb funktioniert aus auch nicht, wenn man an dieser Stelle einfach ein Objekt übergibt, wie z.B. $compile('<p>Hallo {{name}}</p>')({ name: 'Welt' });
.
$interpolate
Ergebnis: String
Beim Verwenden von $interpolate darf sich kein Tag in der Zeichenkette befinden.
Beispiel:
$interpolate('Hallo {{name}}')({ name: 'Welt' });
// => Hallo Welt
$interpolate
unterteilt die Zeichenkette wieder weiter und sucht nach Expressions ({{}}). Auf diese wird der $parse-Service angewendet.
$parse
Ergebnis: String
Wichtig: Beim Verwenden von $parse darf sich keine weitere Expression ({{}}) in der Zeichenkette befinden.
Beispiel:
$parse('name | uppercase')({ name: 'Welt' });
// => WELT
$parse verarbeitet auch Filter.
Noch ein Beispiel im AngularJS-Framework:
Da wir uns die Services jetzt genauer angeschaut haben, können wir auch erklären, wieso wir bei manchen Direktiven magisch Variablen benutzen können.
Ein gutes Beispiel dafür ist ng-click
. ng-click
fügt magisch die Variable $event
hinzu.
<button ng-click="buttonClickFn($event)">Klick mich!</button>
Wenn wir uns die Direktive dazu angucken, ist das Geheimnis schnell gelüftet:
Diese Directive ist extrem vereinfacht. Sie ist abgeleitet vom allgemeinen Fall aus ngEventDirs.js
.directive('ngClick', function($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.on('click', function(event) {
$parse(attrs.ngClick)(scope, { $event: event });
scope.$apply();
});
}
}
});
An dieser Stelle wird $parse
mit einer Besonderheit genutzt. Statt einfach nur einen Scope zu übergeben, kann über einen weiteren Parameter noch ein Objekt übergeben werden. Dieses Objekt wird mit dem Scope zusammengeführt.
Abschluss
Ich hoffe dieser hat euch geholfen, AngularJS etwas besser zu verstehen. Ist noch irgendwas unklar? - Dann füge ich gerne noch Beispiele hinzu.
Inhaltsverzeichnis
Um alle Neuigkeiten zu erfahren, abonniere hier unseren Newsletter!
Newsletter abonnierenSascha Brink
Sascha betreut regelmäßig Angular-Projekte und unterstützt Firmen bei der Ausbildung ihrer Mitarbeiter. Im Jahr 2013 hat er die Platform AngularJS.DE gestartet um das Framework in Deutschland bekannter zu machen. Sascha gibt Angular- und JavaScript-Schulungen auf deutsch und englisch.