Alles, was Sie über ng-template, ng-content, ng-container und * ngTemplateOutlet in Angular wissen müssen

Es war einer dieser Tage, an denen ich an neuen Funktionen für mein Büroprojekt arbeitete. Plötzlich erregte etwas meine Aufmerksamkeit:

Bei der Inspektion des DOM habe ich gesehen ngcontent, wie Angular auf Elemente angewendet wurde. Hmm… wenn sie die Elemente im endgültigen DOM enthalten, wozu dann ? Zu dieser Zeit wurde ich zwischen und verwirrt .

Auf der Suche nach Antworten auf meine Fragen entdeckte ich das Konzept von . Zu meiner Überraschung gab es auch *ngTemplateOutlet. Ich begann meine Reise, um Klarheit über zwei Konzepte zu erlangen, aber jetzt hatte ich vier davon, die fast gleich klangen!

Warst du jemals in dieser Situation? Wenn ja, dann sind Sie hier richtig. Nehmen wir sie also ohne weiteres einzeln auf.

1.

Wie der Name schon sagt die ein Schablonenelement , dass Angular Verwendungen mit strukturellen Richtlinien ( *ngIf, *ngFor, [ngSwitch]und kundenspezifische Richtlinien).

Diese Vorlagenelemente funktionieren nur bei Vorhandensein von Strukturanweisungen . Angular umschließt das Host-Element (auf das die Direktive angewendet wird)und verbraucht dasim fertigen DOM, indem es durch Diagnosekommentare ersetzt wird.

Betrachten Sie ein einfaches Beispiel für *ngIf:

Oben ist die Winkelinterpretation von dargestellt *ngIf. Angular fügt das Host-Element ein, auf das die Direktive angewendet wird, und behält den Host bei. Das endgültige DOM ähnelt dem, was wir am Anfang dieses Artikels gesehen haben:

Verwendung:

Wir haben gesehen, wie Angular verwendet, aber was ist, wenn wir es verwenden möchten? Da diese Elemente nur mit einer strukturellen Richtlinie funktionieren, können wir schreiben als:

Hier homeist eine booleanEigenschaft der Komponente auf trueWert gesetzt. Die Ausgabe des obigen Codes in DOM:

Nichts wurde gerendert! :(

Aber warum können wir unsere Botschaft nicht sehen, selbst wenn wir sie mit einer strukturellen Richtlinie richtig verwendet haben?

Dies war das erwartete Ergebnis. Wie wir bereits besprochen haben, ersetzt Angular das durch diagnostische Kommentare. Zweifellos würde der obige Code keinen Fehler erzeugen, da Angular für Ihren Anwendungsfall vollkommen in Ordnung ist. Man würde nie erfahren, was genau hinter den Kulissen passiert ist.

Vergleichen wir die beiden oben genannten DOMs, die von Angular gerendert wurden:

Wenn Sie genau hinschauen, gibt es im letzten DOM von Beispiel 2 einen zusätzlichen Kommentar-Tag . Der Code, den Angular interpretierte, war:

Angular hat Ihren Host in einen anderen eingepackt und nicht nur den äußeren in diagnostische, sondern auch den inneren Kommentar umgewandelt ! Aus diesem Grund konnten Sie keine Ihrer Nachrichten sehen.

Um dies zu beseitigen, gibt es zwei Möglichkeiten, um das gewünschte Ergebnis zu erzielen:

Methode 1:

Bei dieser Methode stellen Sie Angular das entzuckerte Format zur Verfügung, das nicht weiter verarbeitet werden muss. Diesmal konvertierte Angular nur in Kommentare, ließ jedoch den Inhalt unberührt (sie befinden sich nicht mehr wie im vorherigen Fall). Somit wird der Inhalt korrekt gerendert.

Weitere Informationen zur Verwendung dieses Formats mit anderen Strukturanweisungen finden Sie in diesem Artikel.

Methode 2:

Dies ist ein ziemlich unsichtbares Format und wird selten verwendet (mit zwei Geschwistern ). Hier geben wir einen Vorlagenverweis auf die *ngIfin seiner thenan, um anzugeben, welche Vorlage verwendet werden soll, wenn die Bedingung erfüllt ist.

Die Verwendung mehrerer solcher Geräte wird nicht empfohlen (Sie können sie auch verwenden ), da dies nicht der Zweck ist. Sie werden als Container für Vorlagen verwendet, die an mehreren Stellen wiederverwendet werden können. Wir werden in einem späteren Abschnitt dieses Artikels mehr darüber berichten.

2.

Haben Sie jemals Code geschrieben oder gesehen, der diesem ähnelt:

Der Grund, warum viele von uns diesen Code schreiben, ist die Unfähigkeit, mehrere strukturelle Anweisungen auf einem einzelnen Hostelement in Angular zu verwenden. Jetzt funktioniert dieser Code einwandfrei, führt jedoch mehrere zusätzliche Leerzeichen in das DOM ein, wenn item.ides sich um einen falschen Wert handelt, der möglicherweise nicht erforderlich ist.

Man mag sich nicht um ein einfaches Beispiel wie dieses kümmern, aber für eine große Anwendung mit einem komplexen DOM (um Zehntausende von Daten anzuzeigen) kann dies problematisch werden, da an die Elemente möglicherweise Listener angehängt sind, die noch im Internet vorhanden sind DOM hört Ereignisse.

Was noch schlimmer ist, ist die Verschachtelungsebene, die Sie ausführen müssen, um Ihr Styling (CSS) anzuwenden!

Keine Sorge, wir müssen retten!

Der Angular ist ein Gruppierungselement, das Stile oder Layouts nicht beeinträchtigt, da Angular es nicht in das DOM einfügt .

Wenn wir also unser Beispiel 1 schreiben mit :

Wir erhalten das endgültige DOM als:

Sehen Sie, wir haben diese leeren s losgeworden . Wir sollten verwenden, wenn wir nur mehrere strukturelle Richtlinien anwenden möchten, ohne ein zusätzliches Element in unser DOM einzufügen.

Weitere Informationen finden Sie in den Dokumenten. Es gibt einen anderen Anwendungsfall, in dem eine Vorlage dynamisch in eine Seite eingefügt wird. Ich werde diesen Anwendungsfall im letzten Abschnitt dieses Artikels behandeln.

3.

Sie werden verwendet, um konfigurierbare Komponenten zu erstellen. Dies bedeutet, dass die Komponenten je nach den Anforderungen des Benutzers konfiguriert werden können. Dies ist als Inhaltsprojektion bekannt . Komponenten, die in veröffentlichten Bibliotheken verwendet werden, werden verwendet , um sich selbst konfigurierbar zu machen.

Betrachten Sie eine einfache Komponente:

Der HTML-Inhalt, der innerhalb der öffnenden und schließenden Tags der Komponente übergeben wird, ist der zu projizierende Inhalt. Dies nennen wir Inhaltsprojektion . Der Inhalt wird innerhalb der Komponente gerendert . Auf diese Weise kann der Konsument der Komponente jede benutzerdefinierte Fußzeile innerhalb der Komponente übergeben und genau steuern , wie sie gerendert werden soll.

Mehrere Projektionen:

Was wäre, wenn Sie entscheiden könnten, welche Inhalte wo platziert werden sollen? Anstelle jedes Inhalts, der in einem einzelnen projiziert wird , können Sie auch steuern, wie der Inhalt mit dem selectAttribut von projiziert wird . Es ist eine Elementauswahl erforderlich, um zu entscheiden, welcher Inhalt innerhalb eines bestimmten Projekts projiziert werden soll .

Hier ist wie:

Wir haben die Definition geändert , um eine Projektion mit mehreren Inhalten durchzuführen. Das selectAttribut wählt den Inhaltstyp aus, der in einem bestimmten Element gerendert wird . Hier müssen wir zuerst selectdas Header- h1Element rendern . Wenn der projizierte Inhalt kein h1Element enthält, wird nichts gerendert. Ebenso selectsucht der zweite nach a div. Der Rest des Inhalts wird im letzten mit no gerendert select.

Das Aufrufen der Komponente sieht folgendermaßen aus:

4. * ngTemplateOutlet

… Sie werden als Container für Vorlagen verwendet, die an mehreren Stellen wiederverwendet werden können. Wir werden in einem späteren Abschnitt dieses Artikels mehr darüber berichten.

… Es gibt einen anderen Anwendungsfall, in dem eine Vorlage dynamisch in eine Seite eingefügt wird. Ich werde diesen Anwendungsfall im letzten Abschnitt dieses Artikels behandeln.

In diesem Abschnitt werden wir die beiden oben genannten Punkte diskutieren. *ngTemplateOutletwird für zwei Szenarien verwendet - zum Einfügen einer gemeinsamen Vorlage in verschiedene Abschnitte einer Ansicht, unabhängig von Schleifen oder Bedingungen, und zum Erstellen einer hoch konfigurierten Komponente.

Wiederverwendung von Vorlagen:

Stellen Sie sich eine Ansicht vor, in der Sie eine Vorlage an mehreren Stellen einfügen müssen. Zum Beispiel ein Firmenlogo, das auf einer Website platziert werden soll. Wir können dies erreichen, indem wir die Vorlage für das Logo einmal schreiben und überall in der Ansicht wiederverwenden.

Es folgt das Code-Snippet:

Wie Sie sehen, haben wir die Logo-Vorlage nur einmal geschrieben und dreimal auf derselben Seite mit einer einzigen Codezeile verwendet!

*ngTemplateOutletAkzeptiert auch ein Kontextobjekt, das übergeben werden kann, um die allgemeine Vorlagenausgabe anzupassen. Weitere Informationen zum Kontextobjekt finden Sie in den offiziellen Dokumenten.

Anpassbare Komponenten:

Der zweite Anwendungsfall für *ngTemplateOutlethochindividuelle Komponenten. Betrachten Sie unser vorheriges Beispiel einer Komponente mit einigen Änderungen:

Oben ist die modifizierte Version der Komponente , die drei Eingänge Eigenschaften akzeptiert -  headerTemplate, bodyTemplate, footerTemplate. Es folgt der Ausschnitt für project-content.ts:

Was wir hier erreichen wollen, ist, Kopf-, Körper- und Fußzeile anzuzeigen, wie sie von der übergeordneten Komponente von empfangen wurden . Wenn eine davon nicht bereitgestellt wird, zeigt unsere Komponente an ihrer Stelle die Standardvorlage an. So erstellen Sie eine hochgradig angepasste Komponente.

So verwenden Sie unsere kürzlich geänderte Komponente:

Auf diese Weise übergeben wir die Vorlagenreferenzen an unsere Komponente. Wenn eine davon nicht übergeben wird, rendert die Komponente die Standardvorlage.

ng-content vs. * ngTemplateOutlet

Beide helfen uns dabei, hochgradig kundenspezifische Komponenten zu erhalten, aber welche müssen wir wann auswählen?

Es ist deutlich zu sehen, dass *ngTemplateOutletwir die Standardvorlage besser anzeigen können, wenn keine bereitgestellt wird.

Dies ist bei nicht der Fall ng-content. Der Inhalt wird so gerendert, wie er ist. Sie können den Inhalt maximal aufteilen und mithilfe von selectAttributen an verschiedenen Stellen Ihrer Ansicht rendern . Sie können den Inhalt nicht bedingt rendern ng-content. Sie müssen den Inhalt anzeigen, der vom übergeordneten Element empfangen wird, ohne auf der Grundlage des Inhalts Entscheidungen treffen zu können.

Die Auswahl der beiden Optionen hängt jedoch vollständig von Ihrem Anwendungsfall ab. Zumindest haben wir jetzt eine neue Waffe *ngTemplateOutletin unserem Arsenal, die zusätzlich zu den Funktionen von ng-content!