Angular 2 - style innerHTML

170

Je reçois des morceaux de codes HTML à partir d'appels HTTP. Je mets les blocs HTML dans une variable et l'insère sur ma page avec [innerHTML] mais je ne peux pas styliser le bloc HTML inséré. Quelqu'un a-t-il des suggestions sur la façon dont je pourrais y parvenir?

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

Le HTML que je souhaite styliser est le bloc contenu dans la variable "calendrier".

Jakob Svenningsson
la source
Le style d'où? À partir du composant ou des styles ajoutés à index.html?
Günter Zöchbauer
que voulez-vous dire can not style the inserted HTML block? Montrez-nous ce que vous avez fait pour cela avec un petit extrait de code.
micronyks
J'ai mis à jour mon message avec un extrait de code! :) merci
Jakob Svenningsson
1
J'ai ajouté un lien Plunker à ma réponse
Günter Zöchbauer
@ GünterZöchbauer et si les codes HTML ont un CSS en ligne? comment sera-t-il rendu?
iniravpatel

Réponses:

320

mise à jour 2 ::slotted

::slotted est désormais pris en charge par tous les nouveaux navigateurs et peut être utilisé avec ViewEncapsulation.ShadowDom

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

mise à jour 1 :: ng-deep

/deep/a été obsolète et remplacé par ::ng-deep.

::ng-deep est également déjà marqué comme obsolète, mais aucun remplacement n'est encore disponible.

Lorsque ViewEncapsulation.Nativeest correctement pris en charge par tous les navigateurs et prend en charge le style à travers les frontières shadow DOM, ::ng-deepsera probablement abandonné.

original

Angular ajoute toutes sortes de classes CSS au HTML qu'il ajoute au DOM pour émuler l'encapsulation CSS shadow DOM afin d'éviter que les styles ne saignent à l'intérieur et à l'extérieur des composants. Angular réécrit également le CSS que vous ajoutez pour correspondre à ces classes ajoutées. Pour le HTML ajouté en utilisant [innerHTML]ces classes ne sont pas ajoutés et le CSS réécrit ne correspond pas.

Comme solution de contournement, essayez

  • pour CSS ajouté au composant
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector { 
  background-color: blue;
}
  • pour CSS ajouté à index.html
/* body /deep/ mySelector { */
body ::ng-deep mySelector {
  background-color: green;
}

>>>(et l'équivalent /deep/mais /deep/fonctionne mieux avec SASS) et ::shadowont été ajoutés dans 2.0.0-beta.10. Ils sont similaires aux combinateurs CSS shadow DOM (qui sont obsolètes) et ne fonctionnent qu'avec encapsulation: ViewEncapsulation.Emulatedce qui est la valeur par défaut dans Angular2. Ils fonctionnent probablement aussi avec, ViewEncapsulation.Nonemais ne sont alors ignorés que parce qu'ils ne sont pas nécessaires. Ces combinateurs ne sont qu'une solution intermédiaire jusqu'à ce que des fonctionnalités plus avancées pour le style croisé soient prises en charge.

Une autre approche consiste à utiliser

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

pour tous les composants qui bloquent votre CSS (dépend de l'endroit où vous ajoutez le CSS et de l'emplacement du HTML que vous souhaitez styliser - il peut s'agir de tous les composants de votre application)

Mettre à jour

Exemple Plunker

Günter Zöchbauer
la source
6
Juste une note pour tout le monde, cela ne fonctionne ni avec node-sass, ni avec styleUrl. Only in the styles: [...]
thouliha
12
Avec SASS utiliser /deep/au lieu de>>>
Günter Zöchbauer
1
Vous pouvez ajouter des directives ou des composants dans le contenu avecinneeHTML
Günter Zöchbauer
1
Si le HTML fourni par l'appel HTTP est volumineux et qu'il a un css en ligne, comment cela sera-t-il possible car je n'ai pas les styles prédéfinis, je l'obtiens uniquement à partir du css en ligne @ GünterZöchbauer
iniravpatel
1
Vous avez sauvé la mise dans Angular 8! Merci. Il est difficile de poser la bonne question pour trouver cette réponse!
Pianoman
12

La solution simple que vous devez suivre est

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

constructor(private sanitizer: DomSanitizer){}

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

Si vous essayez de styliser des éléments HTML ajoutés dynamiquement dans un composant Angular, cela peut être utile:

// 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(), '')
}

Je suppose que la convention pour cet attribut n'est pas garantie d'être stable entre les versions d'Angular, de sorte que l'on pourrait rencontrer des problèmes avec cette solution lors de la mise à niveau vers une nouvelle version d'Angular (bien que la mise à jour de cette solution serait probablement triviale en cela Cas).

Trevor
la source
2

Nous retirons contenu fréquemment de nos CMS [innerHTML]="content.title". Nous styles.scssplaçons les classes nécessaires dans le fichier racine de l'application plutôt que dans le fichier scss du composant. Notre CMS supprime volontairement les styles en ligne, nous devons donc avoir préparé des classes que l'auteur peut utiliser dans leur contenu. N'oubliez pas que l'utilisation {{content.title}}dans le modèle ne rendra pas le HTML à partir du contenu.

Lyfo
la source
-3

Si vous utilisez sass comme préprocesseur de style, vous pouvez revenir au compilateur Sass natif pour la dépendance dev en:

npm install node-sass --save-dev

Pour que vous puissiez continuer à utiliser / deep / pour le développement.

Brian Lu
la source