Angular 2 - innerHTML-Styling

170

Ich erhalte Teile von HTML-Codes von HTTP-Aufrufen. Ich habe die HTML-Blöcke in eine Variable eingefügt und sie mit [innerHTML] auf meiner Seite eingefügt, aber ich kann den eingefügten HTML-Block nicht formatieren. Hat jemand einen Vorschlag, wie ich das erreichen könnte?

@Component({selector: 'calendar',
template: '<div [innerHTML]="calendar"></div>',
providers:[HomeService], 
styles: [` 
h3 {color:red;}
`})

Der HTML-Code, den ich formatieren möchte, ist der Block, der in der Variablen "Kalender" enthalten ist.

Jakob Svenningsson
quelle
Stil von wo? Aus der Komponente oder aus Stilen, die hinzugefügt wurden index.html?
Günter Zöchbauer
was meinst du can not style the inserted HTML block? Zeigen Sie uns mit einem kleinen Codeausschnitt, was Sie dafür getan haben.
Mikronyken
Ich habe meinen Beitrag mit einem Code-Snippet aktualisiert! :) danke
Jakob Svenningsson
1
Ich habe meiner Antwort einen Plunker-Link hinzugefügt
Günter Zöchbauer
@ GünterZöchbauer was ist, wenn die HTML-Codes Inline-CSS haben? Wie wird es gerendert?
Iniravpatel

Antworten:

320

Update 2 ::slotted

::slotted wird jetzt von allen neuen Browsern unterstützt und kann mit verwendet werden ViewEncapsulation.ShadowDom

https://developer.mozilla.org/en-US/docs/Web/CSS/::slotted

Update 1 :: ng-deep

/deep/wurde veraltet und ersetzt durch ::ng-deep.

::ng-deep ist ebenfalls bereits als veraltet markiert, es ist jedoch noch kein Ersatz verfügbar.

Wenn ViewEncapsulation.Nativedies von allen Browsern ordnungsgemäß unterstützt wird und das Styling über Schatten-DOM-Grenzen hinweg unterstützt ::ng-deepwird , wird dies wahrscheinlich eingestellt.

Original

Angular fügt dem HTML-Code, den es dem DOM hinzufügt, alle Arten von CSS-Klassen hinzu, um die Schatten-DOM-CSS-Kapselung zu emulieren und das Ausbluten von Komponenten zu verhindern. Angular schreibt auch das hinzugefügte CSS neu, um es diesen hinzugefügten Klassen anzupassen. Für HTML, das mit [innerHTML]diesen Klassen hinzugefügt wurde, werden keine hinzugefügt und das neu geschriebene CSS stimmt nicht überein.

Versuchen Sie es als Problemumgehung

  • für CSS zur Komponente hinzugefügt
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector { 
  background-color: blue;
}
  • für CSS hinzugefügt zu index.html
/* body /deep/ mySelector { */
body ::ng-deep mySelector {
  background-color: green;
}

>>>(und das Äquivalent /deep/, /deep/funktioniert aber besser mit SASS) und ::shadowwurden in 2.0.0-beta.10 hinzugefügt. Sie ähneln den Schatten-DOM-CSS-Kombinatoren (die veraltet sind) und funktionieren nur mit encapsulation: ViewEncapsulation.Emulatedden Standardeinstellungen in Angular2. Sie arbeiten wahrscheinlich auch mit ViewEncapsulation.None, werden dann aber nur ignoriert, weil sie nicht notwendig sind. Diese Kombinatoren sind nur eine Zwischenlösung, bis erweiterte Funktionen für das komponentenübergreifende Styling unterstützt werden.

Ein anderer Ansatz ist zu verwenden

@Component({
  ...
  encapsulation: ViewEncapsulation.None,
})

für alle Komponenten, die Ihr CSS blockieren (hängt davon ab, wo Sie das CSS hinzufügen und wo sich der HTML-Code befindet, den Sie formatieren möchten - möglicherweise alle Komponenten in Ihrer Anwendung)

Aktualisieren

Beispiel Plunker

Günter Zöchbauer
quelle
6
Nur eine Anmerkung für jedermann, dies funktioniert weder mit Node-Sass noch mit StyleUrl. Nur in den Stilen: [...]
Thouliha
12
Mit SASS /deep/anstelle von>>>
Günter Zöchbauer
1
Sie können keine Anweisungen oder Komponenten in Inhalten hinzufügen lassen mitinneeHTML
Günter Zöchbauer
1
Wenn der vom HTTP-Aufruf bereitgestellte HTML-Code groß ist und Inline-CSS enthält, wie wird dies möglich sein, da ich die Stile nicht vordefiniert habe?
Ich
1
Rettete den Tag in Angular 8! Danke. Es ist schwer, die Frage richtig zu stellen, um diese Antwort zu finden!
Pianoman
12

Die einfache Lösung, der Sie folgen müssen, ist

import { DomSanitizer } from '@angular/platform-browser';

constructor(private sanitizer: DomSanitizer){}

transformYourHtml(htmlTextWithStyle) {
    return this.sanitizer.bypassSecurityTrustHtml(htmlTextWithStyle);
}
Sahil Ralkar
quelle
2

Wenn Sie versuchen, dynamisch hinzugefügte HTML-Elemente innerhalb einer Angular-Komponente zu formatieren, kann dies hilfreich sein:

// inside component class...

constructor(private hostRef: ElementRef) { }

getContentAttr(): string {
  const attrs = this.hostRef.nativeElement.attributes
  for (let i = 0, l = attrs.length; i < l; i++) {
    if (attrs[i].name.startsWith('_nghost-c')) {
      return `_ngcontent-c${attrs[i].name.substring(9)}`
    }
  }
}

ngAfterViewInit() {
  // dynamically add HTML element
  dynamicallyAddedHtmlElement.setAttribute(this.getContentAttr(), '')
}

Ich vermute, dass die Konvention für dieses Attribut zwischen Angular-Versionen nicht garantiert stabil ist, so dass beim Upgrade auf eine neue Version von Angular Probleme mit dieser Lösung auftreten können (obwohl das Aktualisieren dieser Lösung wahrscheinlich trivial wäre Fall).

Trevor
quelle
2

Wir ziehen häufig Inhalte aus unserem CMS als [innerHTML]="content.title". Wir platzieren die erforderlichen Klassen in der styles.scssStammdatei der Anwendung und nicht in der scss-Datei der Komponente. Unser CMS entfernt absichtlich Inline-Stile, sodass wir Klassen vorbereitet haben müssen, die der Autor in ihren Inhalten verwenden kann. Denken Sie daran, dass die Verwendung {{content.title}}in der Vorlage kein HTML aus dem Inhalt rendert.

Lyfo
quelle
-3

Wenn Sie sass als Stilpräprozessor verwenden, können Sie für die Dev-Abhängigkeit wieder zum nativen Sass-Compiler wechseln, indem Sie:

npm install node-sass --save-dev

Damit Sie / deep / weiterhin für die Entwicklung verwenden können.

Brian Lu
quelle