Angular 2 - estilo innerHTML

170

Recibo fragmentos de códigos HTML de llamadas HTTP. Pongo los bloques HTML en una variable y los inserto en mi página con [innerHTML] pero no puedo diseñar el bloque HTML insertado. ¿Alguien tiene alguna sugerencia de cómo podría lograr esto?

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

El HTML que quiero diseñar es el bloque contenido en la variable "calendario".

Jakob Svenningsson
fuente
Estilo de donde? Desde dentro del componente o desde estilos agregados a index.html?
Günter Zöchbauer
a que te refieres can not style the inserted HTML block? Muéstrenos lo que hemos hecho por él con un pequeño fragmento de código.
micronyks
¡He actualizado mi publicación con un fragmento de código! :) gracias
Jakob Svenningsson
1
Agregué un enlace Plunker a mi respuesta
Günter Zöchbauer
@ GünterZöchbauer, ¿y si los códigos HTML tienen CSS en línea? ¿Cómo se hará?
iniravpatel

Respuestas:

320

actualización 2 ::slotted

::slotted ahora es compatible con todos los navegadores nuevos y se puede usar con ViewEncapsulation.ShadowDom

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

actualización 1 :: ng-deep

/deep/fue desaprobado y reemplazado por ::ng-deep.

::ng-deep también está marcado como obsoleto, pero aún no hay reemplazo disponible.

Cuando ViewEncapsulation.Nativetodos los navegadores lo admiten correctamente y admite el estilo a través de los límites de DOM de la sombra, ::ng-deepprobablemente se suspenderá.

original

Angular agrega todo tipo de clases CSS al HTML que agrega al DOM para emular la encapsulación CSS DOM del shadow para evitar estilos de sangrado dentro y fuera de los componentes. Angular también reescribe el CSS que agrega para que coincida con estas clases agregadas. Para HTML agregado usando [innerHTML]estas clases no se agregan y el CSS reescrito no coincide.

Como una solución alternativa

  • para CSS agregado al componente
/* :host /deep/ mySelector { */
:host ::ng-deep mySelector { 
  background-color: blue;
}
  • para CSS agregado a index.html
/* body /deep/ mySelector { */
body ::ng-deep mySelector {
  background-color: green;
}

>>>(y el equivalente /deep/pero /deep/funciona mejor con SASS) y ::shadowse agregaron en 2.0.0-beta.10. Son similares a los combinadores CSS DOM de sombra (que están en desuso) y solo funcionan con lo encapsulation: ViewEncapsulation.Emulatedque es el valor predeterminado en Angular2. Probablemente también funcionen, ViewEncapsulation.Nonepero solo se ignoran porque no son necesarios. Estos combinadores son solo una solución intermedia hasta que se admitan características más avanzadas para el diseño de componentes cruzados.

Otro enfoque es usar

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

para todos los componentes que bloquean su CSS (depende de dónde agregue el CSS y dónde está el HTML que desea diseñar, puede que sean todos los componentes de su aplicación)

Actualizar

Plunker de ejemplo

Günter Zöchbauer
fuente
66
Solo una nota para cualquiera, esto no funciona ni con node-sass ni con styleUrl. Solo en los estilos: [...]
thouliha
12
Con el uso de SASS en /deep/lugar de>>>
Günter Zöchbauer
1
No puede tener directivas o componentes en el contenido agregado coninneeHTML
Günter Zöchbauer
1
Si el código HTML proporcionado por HTTP llamada es grande y tiene CSS en línea ¿Cómo va a ser posible, ya que no tengo los estilos predefinidos, que estoy recibiendo desde el CSS en línea única @ GünterZöchbauer
iniravpatel
1
¡Salvó el día en Angular 8! Gracias ¡Es difícil hacer la pregunta correcta para encontrar esta respuesta!
Pianoman
12

La solución simple que debes seguir es

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

constructor(private sanitizer: DomSanitizer){}

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

Si intenta diseñar elementos HTML añadidos dinámicamente dentro de un componente angular, esto podría ser útil:

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

Supongo que no se garantiza que la convención para este atributo sea estable entre las versiones de Angular, por lo que uno podría tener problemas con esta solución al actualizar a una nueva versión de Angular (aunque la actualización de esta solución probablemente sería trivial en ese sentido). caso).

Trevor
fuente
2

Extraemos contenido con frecuencia de nuestro CMS como [innerHTML]="content.title". styles.scssColocamos las clases necesarias en el archivo raíz de la aplicación en lugar de en el archivo scss del componente. Nuestro CMS elimina deliberadamente los estilos en línea, por lo que debemos tener clases preparadas que el autor pueda usar en su contenido. Recuerde que usar {{content.title}}en la plantilla no representará html del contenido.

Lyfo
fuente
-3

Si está utilizando sass como preprocesador de estilo, puede volver al compilador Sass nativo para la dependencia del desarrollador de la siguiente manera:

npm install node-sass --save-dev

Para que pueda seguir usando / deep / para el desarrollo.

Brian Lu
fuente