Estoy escribiendo una aplicación angular y tengo una respuesta HTML que quiero mostrar.
¿Cómo puedo hacer eso? Si simplemente uso la sintaxis de enlace {{myVal}}
, codifica todos los caracteres HTML (por supuesto).
Necesito de alguna manera vincular el innerHTML
de div
a al valor de la variable.
Respuestas:
La sintaxis correcta es la siguiente:
Referencia de documentación
fuente
Angular 2.0.0 y Angular 4.0.0 final
Para contenido seguro solo
DOMSanitizer
El HTML potencialmente inseguro debe marcarse explícitamente como confiable usando Angulars DOM sanitizer para que no elimine partes potencialmente inseguras del contenido
con una pipa como
Consulte también En RC.1, algunos estilos no se pueden agregar utilizando la sintaxis de enlace
Y documentos: https://angular.io/api/platform-browser/DomSanitizer
Advertencia de seguridad
Confiar en el HTML agregado por el usuario puede representar un riesgo de seguridad. Los documentos mencionados anteriormente indican:
Marcado angular
Algo como
con
no hará que Angular procese nada específico de Angular
foo
. Angular reemplaza el marcado específico angular en tiempo de compilación con código generado. El marcado agregado en tiempo de ejecución no será procesado por Angular .Para agregar HTML que contenga marcado específico angular (propiedad o enlace de valor, componentes, directivas, tuberías, ...) es necesario agregar el módulo dinámico y compilar componentes en tiempo de ejecución. Esta respuesta proporciona más detalles. ¿Cómo puedo usar / crear plantillas dinámicas para compilar componentes dinámicos con Angular 2.0?
fuente
import { BrowserModule, DomSanitizer } from '@angular/platform-browser'
import { Pipe } from '@angular/core'
[innerHtml]
es una gran opción en la mayoría de los casos, pero falla con cadenas realmente grandes o cuando necesita un estilo codificado en html.Me gustaría compartir otro enfoque:
Todo lo que necesitas hacer es crear un div en tu archivo html y darle alguna identificación:
Luego, en su componente Angular 2, cree una referencia a este objeto (TypeScript aquí):
Luego, simplemente use la
loadData
función para agregar texto al elemento html.Es solo una forma de hacerlo usando JavaScript nativo, pero en un entorno angular. No lo recomiendo porque hace que el código sea más desordenado, pero a veces no hay otra opción.
Ver también Angular 2 - estilo innerHTML
fuente
nativeElement
directamente a propiedades que se consideran malas prácticas. Estoy seguro de que[innerHTML]="..."
hace lo mismo debajo del capó, pero en la buena práctica de Angular2.[innerHTML]
cadenas grandes en Angular2?[innerHtml]
elimina el estilo codificado en el HTML. Para integrar un editor wysiwyg, tuve que usar el enfoque que se detalla aquí.[innerHTML]
enfoque no lo hizo.En [email protected]:
El enlace HTML no funcionará cuando use un
{{interpolation}}
, use una "Expresión" en su lugar:inválido
-> arroja un error (Interpolación en lugar de Expresión esperada)
correcto
-> esta es la forma correcta.
Puede agregar elementos adicionales a la expresión, como:
insinuación
Angular agregará usando
[innerHTML]
(o agregado dinámicamente por otros medios comoelement.appenChild()
o similares) no será procesado por Angular de ninguna manera, excepto la desinfección por motivos de seguridad.Tales cosas solo funcionan cuando el HTML se agrega estáticamente a una plantilla de componentes. Si necesita esto, puede crear un componente en tiempo de ejecución como se explica en ¿Cómo puedo usar / crear plantilla dinámica para compilar Componente dinámico con Angular 2.0?
fuente
Usar [innerHTML] directamente sin usar el desinfectante DOM de Angular no es una opción si contiene contenido creado por el usuario. La tubería safeHtml sugerida por @ GünterZöchbauer en su respuesta es una forma de desinfectar el contenido. La siguiente directiva es otra:
Para ser utilizado
fuente
Can't bind to 'safeHtml' since it isn't a known property of 'div'.
ng-version 2.4.4constructor( private sanitizer: Sanitizer) {}
y vincular el resultado a lo que necesite, también el uso de ElementRef no está sugerido.Esto funciona para mí:
<div innerHTML = "{{ myVal }}"></div>
(Angular2, Alpha 33)Según otro SO: Insertar HTML del servidor en DOM con angular2 (manipulación general de DOM en Angular2) , "inner-html" es equivalente a "ng-bind-html" en Angular 1.X
fuente
Solo para obtener una respuesta completa, si su contenido html está en una variable componente, también puede usar:
fuente
Pido disculpas si me estoy perdiendo el punto aquí, pero me gustaría recomendar un enfoque diferente:
Creo que es mejor devolver datos sin procesar de la aplicación del lado del servidor y vincularlos a una plantilla en el lado del cliente. Esto genera solicitudes más ágiles, ya que solo está devolviendo json desde su servidor.
Para mí, no parece tener sentido usar Angular si todo lo que estás haciendo es obtener html del servidor e inyectarlo "tal cual" en el DOM.
Sé que Angular 1.x tiene un enlace html, pero aún no he visto una contraparte en Angular 2.0. Sin embargo, podrían agregarlo más tarde. De todos modos, todavía consideraría una API de datos para su aplicación Angular 2.0.
Tengo algunas muestras aquí con un enlace de datos simple si está interesado: http://www.syntaxsuccess.com/viewarticle/angular-2.0-examples
fuente
Aquí ya se proporcionó una respuesta breve: usar
<div [innerHTML]="yourHtml">
enlace.Sin embargo, el resto de los consejos mencionados aquí pueden ser engañosos. Angular tiene un mecanismo de desinfección incorporado cuando se une a propiedades como esa. Dado que Angular no es una biblioteca dedicada a la desinfección, es demasiado celoso de contenido sospechoso para no correr ningún riesgo. Por ejemplo, desinfecta todo el contenido SVG en una cadena vacía.
Es posible que escuche consejos para "desinfectar" su contenido al usarlo
DomSanitizer
para marcar el contenido como seguro conbypassSecurityTrustXXX
métodos. También hay sugerencias para usar tubería para hacer eso y esa tubería a menudo se llamasafeHtml
.Todo esto es engañoso porque en realidad pasa por alto la desinfección , no la desinfección de su contenido. Esto podría ser un problema de seguridad porque si alguna vez haces esto en contenido proporcionado por el usuario o en algo de lo que no estás seguro, te abres a un ataque de código malicioso.
Si Angular elimina algo que necesita mediante su desinfección incorporada, lo que puede hacer en lugar de deshabilitarlo es delegar la desinfección real a una biblioteca dedicada que sea buena para esa tarea. Por ejemplo, DOMPurify.
He creado una biblioteca de contenedor para que pueda usarse fácilmente con Angular: https://github.com/TinkoffCreditSystems/ng-dompurify
También tiene una tubería para desinfectar declarativamente HTML:
La diferencia con las tuberías sugeridas aquí es que realmente hace la desinfección a través de DOMPurify y, por lo tanto, funciona para SVG.
Una cosa a tener en cuenta es que DOMPurify es excelente para desinfectar HTML / SVG, pero no CSS. Para que pueda proporcionar el desinfectante CSS de Angular para manejar CSS:
Es interno -
ɵ
prefijo hense , pero así es como el equipo de Angular lo usa en sus propios paquetes de todos modos. Esa biblioteca también funciona para Angular Universal y el entorno de renedring del lado del servidor.fuente
Simplemente use el
[innerHTML]
atributo en su HTML , algo como esto a continuación:¡Usar
{{myVal}}
NO funciona como se esperaba! Esto no recogerá las etiquetas HTML como<p>
,<strong>
etc. y lo pasará solo como cadenas ...Imagine que tiene este código en su componente:
const myVal:string ='<strong>Stackoverflow</strong> is <em>helpful!</em>'
Si usa
{{myVal}}
, obtendrá esto en la vista:pero el uso
[innerHTML]="myVal"
hace que el resultado sea el esperado de esta manera:¡Stackoverflow es útil!
fuente
Puede aplicar varias canalizaciones para estilo, enlace y HTML como se indica en .html
y en la tubería .ts para el desinfectante 'URL'
tubería para desinfectante 'HTML'
esto se aplicará sin perturbar ningún estilo y evento de clic de enlace
fuente
El innerHtml es una propiedad de los elementos HTML, lo que le permite establecer que es html contenido de programación. También hay una propiedad innerText que define el contenido como texto sin formato.
El
[attributeName]="value"
cuadro de recuadro que rodea el atributo define un enlace de entrada angular. Eso significa que el valor de la propiedad (en su caso innerHtml) está vinculado a la expresión dada, cuando el resultado de la expresión cambia, el valor de la propiedad también cambia.Entonces, básicamente, le
[innerHtml]
permite vincular y cambiar dinámicamente el contenido html del elemento HTML dado.fuente
En Angular 2 puedes hacer 3 tipos de enlaces:
[property]="expression"
-> Cualquier propiedad html puede vincularse a unaexpresión. En este caso, si la expresión cambia, la propiedad se actualizará, pero esto no funciona de otra manera.
(event)="expression"
-> Cuando el evento se activa, ejecuta la expresión.[(ngModel)]="property"
-> Vincula la propiedad de js (o ts) a html. Cualquier actualización de esta propiedad se notará en todas partes.Una expresión puede ser un valor, un atributo o un método. Por ejemplo: '4', 'controller.var', 'getValue ()'
Ejemplo aquí
fuente
La forma de agregar elementos dinámicamente a DOM, como se explica en el documento de Angular 2, es usando la clase ViewContainerRef de @ Angular / core.
Lo que debe hacer es declarar una directiva que implementará ViewContainerRef y actuará como un marcador de posición en su DOM.
Directiva
Luego, en la plantilla donde desea inyectar el componente:
HTML
Luego, desde el código del componente inyectado, inyectará el componente que contiene el HTML que desea:
Agregué una aplicación de demostración completamente funcional en Angular 2 para agregar componentes dinámicamente a la demostración DOM
fuente
Puede usar varios enfoques para lograr la solución. Como ya se dijo en la respuesta aprobada, puede usar:
dependiendo de lo que intente lograr, también puede probar otras cosas como DOM de javascript (no recomendado, las operaciones DOM son lentas):
Presentación
Componente
Enlace de propiedad
Javascript DOM HTML externo
fuente
getElementsById
cualquier otro método de selección es malo porque podría capturar elementos que pertenecen a componentes completamente diferentes si contienen elementos con la misma identificación (u otros criterios).Siempre podemos pasar contenido html a la
innerHTML
propiedad para representar contenido dinámico html, pero ese contenido html dinámico también puede infectarse o maliciarse. Entonces, antes de pasar contenido dinámico ainnerHTML
nosotros, siempre debemos asegurarnos de que el contenido esté desinfectado (usandoDOMSanitizer
) para que podamos escapar de todo el contenido malicioso.Prueba debajo de la tubería:
fuente
style: background-color
todas las cosas se pueden quitar y, por lo tanto, es mejor comenzar a usar esto desde el principio o se confundirá más tarde.Si desea eso en Angular 2 o Angular 4 y también desea mantener CSS en línea, puede usar
fuente
También puede vincular las propiedades de la clase de componente angular con la plantilla utilizando la forma canónica como se muestra a continuación:
Documentación angular: https://angular.io/guide/template-syntax#property-binding-property
Vea el ejemplo de trabajo de stackblitz aquí
fuente
Trabajando en Angular v2.1.1
fuente
<div _ngcontent-luf-0=""></div>
para mí. Eldiv
esta vacio.Si tiene plantillas en su aplicación angular (o cualquier marco), y devuelve plantillas HTML desde su backend a través de una solicitud / respuesta HTTP, está mezclando plantillas entre el frontend y el backend.
¿Por qué no dejar las plantillas en la interfaz (sugeriría eso) o en el servidor (bastante intransparente)?
Y si mantiene las plantillas en la interfaz, ¿por qué no solo responde con JSON para las solicitudes al backend? Ni siquiera tiene que implementar una estructura RESTful, pero mantener las plantillas a un lado hace que su código sea más transparente.
¡Esto pagará cuando alguien más tenga que hacer frente a su código (o incluso usted mismo está volviendo a ingresar su propio código después de un tiempo)!
Si lo hace bien, tendrá componentes pequeños con plantillas pequeñas y, lo mejor de todo, si su código es imba, ¡alguien que no conozca los lenguajes de codificación podrá comprender sus plantillas y su lógica! Además, mantenga sus funciones / métodos lo más pequeños que pueda. Eventualmente descubrirá que mantener, refactorizar, revisar y agregar características será mucho más fácil en comparación con funciones / métodos / clases grandes y mezclar plantillas y lógica entre el frontend y el back-end, y mantener la mayor parte de la lógica en el back-end. si su interfaz necesita ser más flexible (por ejemplo, escribir una interfaz de Android o cambiar a un marco de interfaz diferente).
Filosofía, hombre :)
pd: no tiene que implementar un código 100% limpio, porque es muy costoso, especialmente si tiene que motivar a los miembros del equipo;) pero: debe encontrar un buen equilibrio entre un enfoque de código más limpio y lo que tiene (tal vez ya está bastante limpio)
revisa el libro si puedes y deja que entre en tu alma: https://de.wikipedia.org/wiki/Clean_Code
fuente