Ich schreibe eine Angular-Anwendung und habe eine HTML-Antwort, die ich anzeigen möchte.
Wie mache ich das? Wenn ich einfach die Bindungssyntax verwende, werden {{myVal}}
(natürlich) alle HTML-Zeichen codiert.
Ich muss irgendwie das innerHTML
von a div
an den variablen Wert binden .
Antworten:
Die richtige Syntax lautet wie folgt:
Dokumentationsreferenz
quelle
Angular 2.0.0 und Angular 4.0.0 final
Nur für sichere Inhalte
DOMSanitizer
Potenziell unsicheres HTML muss mit Angulars DOM Sanitizer explizit als vertrauenswürdig markiert werden, damit potenziell unsichere Teile des Inhalts nicht entfernt werden
mit einer Pfeife wie
Siehe auch In RC.1 können einige Stile nicht mithilfe der Bindungssyntax hinzugefügt werden
Und Dokumente: https://angular.io/api/platform-browser/DomSanitizer
Sicherheitswarnung
Das Vertrauen in vom Benutzer hinzugefügtes HTML kann ein Sicherheitsrisiko darstellen. In den oben genannten Dokumenten heißt es :
Winkelmarkierung
Etwas wie
mit
veranlasst Angular nicht, irgendetwas Angular-spezifisches in zu verarbeiten
foo
. Angular ersetzt Angular-spezifisches Markup zur Erstellungszeit durch generierten Code. Zur Laufzeit hinzugefügtes Markup wird von Angular nicht verarbeitet .Um HTML hinzuzufügen, das Angular-spezifisches Markup enthält (Eigenschafts- oder Wertebindung, Komponenten, Direktiven, Pipes, ...), müssen Sie das dynamische Modul hinzufügen und Komponenten zur Laufzeit kompilieren. Diese Antwort enthält weitere Details. Wie kann ich eine dynamische Vorlage verwenden / erstellen, um eine dynamische Komponente mit Angular 2.0 zu kompilieren?
quelle
import { BrowserModule, DomSanitizer } from '@angular/platform-browser'
import { Pipe } from '@angular/core'
[innerHtml]
ist in den meisten Fällen eine großartige Option, schlägt jedoch bei sehr großen Zeichenfolgen fehl oder wenn Sie ein hartcodiertes Styling in HTML benötigen.Ich möchte einen anderen Ansatz teilen:
Alles, was Sie tun müssen, ist, ein Div in Ihrer HTML-Datei zu erstellen und ihr eine ID zu geben:
Erstellen Sie dann in Ihrer Angular 2-Komponente einen Verweis auf dieses Objekt (TypeScript hier):
Verwenden Sie dann einfach die
loadData
Funktion, um Text an das HTML-Element anzuhängen.Es ist nur eine Möglichkeit, dies mit nativem Javascript zu tun, jedoch in einer Angular-Umgebung. Ich empfehle es nicht, weil es den Code unordentlicher macht, aber manchmal gibt es keine andere Option.
Siehe auch Angular 2 - innerHTML-Styling
quelle
nativeElement
direkt auf Eigenschaften zugreifen, die als schlechte Praxis angesehen werden. Ich bin mir sicher,[innerHTML]="..."
dass ich das auch unter der Haube mache, aber auf gute Angular2-Art und Weise.[innerHTML]
und großen Zeichenfolgen in Angular2 gehabt?[innerHtml]
Entfernt das im HTML-Code fest codierte Styling. Um einen wysiwyg-Editor zu integrieren, musste ich den hier aufgeführten Ansatz verwenden.[innerHTML]
Ansatz dies nicht tat.Auf [email protected]:
Die HTML-Bindung funktioniert nicht, wenn Sie einen verwenden
{{interpolation}}
. Verwenden Sie stattdessen einen "Ausdruck":ungültig
-> löst einen Fehler aus (Interpolation statt erwarteter Ausdruck)
richtig
-> das ist der richtige Weg.
Sie können dem Ausdruck zusätzliche Elemente hinzufügen, z.
Hinweis
HTML-Code, der mit
[innerHTML]
(oder dynamisch auf andere Weise wieelement.appenChild()
oder ähnlich) dynamisch hinzugefügt wurde , wird von Angular in keiner Weise verarbeitet, außer aus Sicherheitsgründen.Solche Dinge funktionieren nur, wenn der HTML-Code statisch zu einer Komponentenvorlage hinzugefügt wird. Wenn Sie dies benötigen, können Sie zur Laufzeit eine Komponente erstellen, wie unter Wie kann ich eine dynamische Vorlage zum Kompilieren einer dynamischen Komponente mit Angular 2.0 verwenden / erstellen?
quelle
Die direkte Verwendung von [innerHTML] ohne Verwendung von Angulars DOM-Desinfektionsprogramm ist keine Option, wenn es vom Benutzer erstellte Inhalte enthält. Die von @ GünterZöchbauer in seiner Antwort vorgeschlagene safeHtml-Pipe ist eine Möglichkeit, den Inhalt zu bereinigen . Die folgende Richtlinie ist eine andere:
Verwendet werden
quelle
Can't bind to 'safeHtml' since it isn't a known property of 'div'.
constructor( private sanitizer: Sanitizer) {}
und das Ergebnis an alles binden, was Sie benötigen. Auch die Verwendung von ElementRef wird dringend empfohlen.Das funktioniert bei mir:
<div innerHTML = "{{ myVal }}"></div>
(Angular2, Alpha 33)Gemäß einem anderen SO: Einfügen von HTML vom Server in das DOM mit angle2 (allgemeine DOM-Manipulation in Angular2) entspricht "inner-html" "ng-bind-html" in Angular 1.X.
quelle
Um eine vollständige Antwort zu erhalten, können Sie, wenn sich Ihr HTML-Inhalt in einer Komponentenvariablen befindet, auch Folgendes verwenden:
quelle
Ich entschuldige mich, wenn ich den Punkt hier verpasse, aber ich möchte einen anderen Ansatz empfehlen:
Ich denke, es ist besser, Rohdaten von Ihrer serverseitigen Anwendung zurückzugeben und sie an eine Vorlage auf der Clientseite zu binden. Dies sorgt für schnellere Anfragen, da Sie nur json von Ihrem Server zurückgeben.
Für mich scheint es nicht sinnvoll zu sein, Angular zu verwenden, wenn Sie nur HTML vom Server abrufen und es "wie es ist" in das DOM einfügen.
Ich weiß, dass Angular 1.x eine HTML-Bindung hat, aber ich habe noch kein Gegenstück in Angular 2.0 gesehen. Sie könnten es aber später hinzufügen. Auf jeden Fall würde ich immer noch eine Daten-API für Ihre Angular 2.0-App in Betracht ziehen.
Ich habe hier einige Beispiele mit einer einfachen Datenbindung, wenn Sie interessiert sind: http://www.syntaxsuccess.com/viewarticle/angular-2.0-examples
quelle
Hier wurde bereits eine kurze Antwort gegeben:
<div [innerHTML]="yourHtml">
Bindung verwenden.Der Rest der hier genannten Ratschläge kann jedoch irreführend sein. Angular verfügt über einen integrierten Desinfektionsmechanismus, wenn Sie an solche Eigenschaften binden. Da Angular keine dedizierte Desinfektionsbibliothek ist, ist es gegenüber verdächtigen Inhalten übereifrig, kein Risiko einzugehen. Beispielsweise werden alle SVG-Inhalte in leere Zeichenfolgen bereinigt.
Möglicherweise hören Sie Ratschläge, Ihren Inhalt zu "bereinigen", indem Sie ihn
DomSanitizer
mitbypassSecurityTrustXXX
Methoden als sicher markieren . Es gibt auch Vorschläge, Pipe zu verwenden, und diese Pipe wird oft genanntsafeHtml
.All dies ist irreführend, weil es tatsächlich die Desinfektion umgeht und nicht die Bereinigung Ihrer Inhalte. Dies kann ein Sicherheitsrisiko sein, denn wenn Sie dies jemals für vom Benutzer bereitgestellte Inhalte oder für etwas tun, bei dem Sie sich nicht sicher sind, öffnen Sie sich für Angriffe mit bösartigem Code.
Wenn Angular durch die integrierte Bereinigung etwas entfernt, das Sie benötigen, können Sie die eigentliche Bereinigung an eine dedizierte Bibliothek delegieren, die für diese Aufgabe geeignet ist, anstatt sie zu deaktivieren. Zum Beispiel - DOMPurify.
Ich habe eine Wrapper-Bibliothek dafür erstellt, damit sie problemlos mit Angular verwendet werden kann: https://github.com/TinkoffCreditSystems/ng-dompurify
Es hat auch eine Pipe, um HTML deklarativ zu bereinigen:
Der Unterschied zu den hier vorgeschlagenen Rohren besteht darin, dass sie tatsächlich die Desinfektion über DOMPurify durchführen und daher für SVG funktionieren.
Eine Sache, die Sie beachten sollten, ist, dass DOMPurify sich hervorragend zum Bereinigen von HTML / SVG eignet, nicht jedoch von CSS. So können Sie Angulars CSS-Desinfektionsmittel für CSS bereitstellen:
Es ist ein internes
ɵ
Präfix - hense , aber so verwendet es das Angular-Team sowieso auch für seine eigenen Pakete. Diese Bibliothek funktioniert auch für Angular Universal- und serverseitige Renedring-Umgebungen.quelle
Verwenden
[innerHTML]
Sie einfach ein Attribut in Ihrem HTML- Code.Verwendung
{{myVal}}
funktioniert NICHT wie erwartet! Dies wird nicht abholen die HTML - Tags wie<p>
,<strong>
etc und geben es nur als Strings ...Stellen Sie sich vor, Sie haben diesen Code in Ihrer Komponente:
const myVal:string ='<strong>Stackoverflow</strong> is <em>helpful!</em>'
Wenn Sie verwenden
{{myVal}}
, erhalten Sie dies in der Ansicht:Mit using
[innerHTML]="myVal"
wird das Ergebnis jedoch wie erwartet ausgeführt:Stackoverflow ist hilfreich!
quelle
Sie können mehrere Pipe für Stil, Link und HTML wie folgt in .html anwenden
und in .ts-Pipe für 'URL'-Desinfektionsmittel
Pipe für 'HTML'-Desinfektionsmittel
Dies gilt sowohl ohne Störung des Stils als auch des Link-Klick-Ereignisses
quelle
Das innerHtml ist eine Eigenschaft von HTML-Elemente, die Sie es HTML-Inhalt programmatisch festlegen können. Es gibt auch eine innerText-Eigenschaft, die den Inhalt als einfachen Text definiert.
Das
[attributeName]="value"
das Attribut umgebende Box-Klammer definiert eine Winkeleingabebindung. Das bedeutet, dass der Wert der Eigenschaft (in Ihrem Fall innerHtml) an den angegebenen Ausdruck gebunden ist. Wenn sich das Ausdrucksergebnis ändert, ändert sich auch der Eigenschaftswert.Grundsätzlich
[innerHtml]
können Sie also den HTML-Inhalt des angegebenen HTML-Elements binden und dynamisch ändern.quelle
In Angular 2 können Sie drei Arten von Bindungen ausführen:
[property]="expression"
-> Jede HTML-Eigenschaft kann mit einemAusdruck verknüpft werden . In diesem Fall wird die Eigenschaft "Ausdrucksänderungen" aktualisiert, dies funktioniert jedoch nicht andersherum.
(event)="expression"
-> Wenn das Ereignis aktiviert ist, führen Sie den Ausdruck aus.[(ngModel)]="property"
-> Bindet die Eigenschaft von js (oder ts) an HTML. Jedes Update dieser Eigenschaft ist überall spürbar.Ein Ausdruck kann ein Wert, ein Attribut oder eine Methode sein. Zum Beispiel: '4', 'controller.var', 'getValue ()'
Beispiel hier
quelle
Die Möglichkeit, Elemente dynamisch zu DOM hinzuzufügen, wie in Angular 2-Dokument erläutert, besteht in der Verwendung der ViewContainerRef-Klasse von @ Angular / core.
Sie müssen lediglich eine Direktive deklarieren, die ViewContainerRef implementiert und sich wie ein Platzhalter in Ihrem DOM verhält.
Richtlinie
Dann in der Vorlage, in die Sie die Komponente einfügen möchten:
HTML
Anschließend fügen Sie aus dem Code der injizierten Komponente die Komponente ein, die den gewünschten HTML-Code enthält:
Ich habe eine voll funktionsfähige Demo-App für Angular 2 hinzugefügt, die der DOM-Demo dynamisch Komponenten hinzufügt
quelle
Sie können verschiedene Ansätze verwenden, um die Lösung zu erreichen. Wie bereits in der genehmigten Antwort erwähnt, können Sie Folgendes verwenden:
Abhängig davon, was Sie erreichen möchten, können Sie auch andere Dinge wie Javascript-DOM ausprobieren (nicht empfohlen, DOM-Vorgänge sind langsam):
Präsentation
Komponente
Eigenschaftsbindung
Javascript DOM Äußeres HTML
quelle
getElementsById
oder einer anderen Auswahlmethode schlecht, da möglicherweise Elemente erfasst werden, die zu völlig unterschiedlichen Komponenten gehören, wenn sie Elemente mit derselben ID (oder anderen Kriterien) enthalten.Wir können jederzeit HTML-Inhalte an
innerHTML
Eigenschaften übergeben, um dynamische HTML-Inhalte zu rendern, aber diese dynamischen HTML-Inhalte können auch infiziert oder bösartig sein. BevorinnerHTML
wir also dynamischen Inhalt an übergeben , sollten wir immer sicherstellen, dass der Inhalt bereinigt ist (mitDOMSanitizer
), damit wir allen schädlichen Inhalten entkommen können.Versuchen Sie es unter dem Rohr:
quelle
style: background-color
alle Dinge entfernt werden, und deshalb ist es am besten, einfach von vorne damit zu beginnen, sonst werden Sie später sehr verwirrt.Wenn Sie dies in Angular 2 oder Angular 4 möchten und auch Inline-CSS beibehalten möchten, können Sie es verwenden
quelle
Sie können die Eigenschaften der Winkelkomponentenklasse auch mit einer Vorlage in kanonischer Form wie folgt verknüpfen:
Winkeldokumentation: https://angular.io/guide/template-syntax#property-binding-property
Siehe Arbeitsstapelblitz- Beispiel hier
quelle
Arbeiten in Angular v2.1.1
quelle
<div _ngcontent-luf-0=""></div>
für mich. Dasdiv
ist leer.Wenn Ihre eckige Anwendung (oder ein beliebiges Framework) Vorlagen enthält und Sie HTML-Vorlagen von Ihrem Backend über eine HTTP-Anforderung / Antwort zurückgeben, verwechseln Sie Vorlagen zwischen dem Frontend und dem Backend.
Warum lassen Sie die Vorlagen nicht einfach entweder im Frontend (das würde ich vorschlagen) oder im Backend (ziemlich intransparent imo)?
Wenn Sie Vorlagen im Frontend behalten, antworten Sie einfach mit JSON auf Anfragen an das Backend. Sie müssen nicht einmal eine RESTful-Struktur implementieren, aber wenn Sie Vorlagen auf einer Seite halten, wird Ihr Code transparenter.
Dies zahlt sich aus, wenn jemand anderes mit Ihrem Code fertig werden muss (oder sogar Sie selbst nach einer Weile Ihren eigenen Code erneut eingeben)!
Wenn Sie es richtig machen, haben Sie kleine Komponenten mit kleinen Vorlagen, und das Beste ist, wenn Ihr Code imba ist, kann jemand, der keine Programmiersprachen kennt, Ihre Vorlagen und Ihre Logik verstehen! Halten Sie Ihre Funktionen / Methoden außerdem so klein wie möglich. Sie werden schließlich feststellen, dass das Verwalten, Umgestalten, Überprüfen und Hinzufügen von Funktionen im Vergleich zu großen Funktionen / Methoden / Klassen und dem Verwechseln von Vorlagen und Logik zwischen Frontend und Backend viel einfacher ist - und dass Sie so viel Logik wie möglich im Backend behalten wenn Ihr Frontend flexibler sein muss (z. B. Schreiben eines Android-Frontends oder Wechseln zu einem anderen Frontend-Framework).
Philosophie, Mann :)
ps: du musst nicht 100% sauberen Code implementieren, weil es sehr teuer ist - besonders wenn du Teammitglieder motivieren musst;) aber: du solltest ein gutes Gleichgewicht zwischen einem Ansatz für saubereren Code und dem finden, was du hast (vielleicht auch) ist schon ziemlich sauber)
Überprüfen Sie das Buch, wenn Sie können, und lassen Sie es in Ihre Seele eindringen: https://de.wikipedia.org/wiki/Clean_Code
quelle