Enlace HTML angular


841

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 innerHTMLde diva al valor de la variable.



1
Puse un video de respuesta para explicar la solución y dar un ejemplo: youtube.com/watch?v=Pem2UXp7TXA
Caleb Grams

¿Qué pasa si la variable contiene una etiqueta angular o etiqueta definida por el usuario como <span [routerLink] = ['some-router']> link </span>
G. Muqtada

Respuestas:


1338

La sintaxis correcta es la siguiente:

<div [innerHTML]="theHtmlString"></div>

Referencia de documentación



14
¿Hay alguna forma de forzar a angular para que ejecute su enlace en los elementos de ese innerHTML? Necesito usar un <a [router-linkfont>="..."> </a>, y quiero proporcionarlo desde un html externo.
thouliha

44
@thouliha Recomiendo comenzar una nueva publicación con respecto a su pregunta.
prolink007

44
Representa la cadena en mi caso, pero hace algo al marcado. Parece haber eliminado los atributos en el marcado. Estoy en 2.4.6
paqogomez

2
@paqogomez Sí, elimina todo lo que considere inseguro
Juan Mendes

312

Angular 2.0.0 y Angular 4.0.0 final

Para contenido seguro solo

<div [innerHTML]="myVal"></div>

DOMSanitizer

El HTML potencialmente inseguro debe marcarse explícitamente como confiable usando Angulars DOM sanitizer para que no elimine partes potencialmente inseguras del contenido

<div [innerHTML]="myVal | safeHtml"></div>

con una pipa como

@Pipe({name: 'safeHtml'})
export class Safe {
  constructor(private sanitizer:DomSanitizer){}

  transform(style) {
    return this.sanitizer.bypassSecurityTrustHtml(style);
    //return this.sanitizer.bypassSecurityTrustStyle(style);
    // return this.sanitizer.bypassSecurityTrustXxx(style); - see docs
  }
}

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:

Llamar a cualquiera de las bypassSecurityTrust...API deshabilita la desinfección integrada de Angular para el valor pasado. Verifique y audite cuidadosamente todos los valores y rutas de código que entran en esta llamada. Asegúrese de que los datos de los usuarios se hayan escapado adecuadamente para este contexto de seguridad. Para más detalles, consulte la Guía de seguridad .

Marcado angular

Algo como

class FooComponent {
  bar = 'bar';
  foo = `<div>{{bar}}</div>
    <my-comp></my-comp>
    <input [(ngModel)]="bar">`;

con

<div [innerHTML]="foo"></div>

no hará que Angular procese nada específico de Angularfoo . 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?


13
Esta debería ser la respuesta. Presta atención a las dos líneas que están comentadas. En realidad, es el segundo que maneja HTML.
paqogomez

8
asegúrese deimport { BrowserModule, DomSanitizer } from '@angular/platform-browser'
paqogomez

44
Tambiénimport { Pipe } from '@angular/core'
Appulus

1
Esta es la respuesta, aquí mismo! Estaba buscando los detalles sobre lo que en NG2 reemplazó $ SCE de NG1. ;)
jrista

2
Gran respuesta. Resuelto mi problema Muchas gracias. En caso de que alguien no esté seguro de cómo usar la tubería en un componente (como yo lo estaba): angular.io/guide/pipes ¡ Solo agréguela a sus declaraciones en el módulo correspondiente y listo!
Alejandro Nagy

169

[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:

<div #dataContainer></div>

Luego, en su componente Angular 2, cree una referencia a este objeto (TypeScript aquí):

import { Component, ViewChild, ElementRef } from '@angular/core';

@Component({
    templateUrl: "some html file"
})
export class MainPageComponent {

    @ViewChild('dataContainer') dataContainer: ElementRef;

    loadData(data) {
        this.dataContainer.nativeElement.innerHTML = data;
    }
}

Luego, simplemente use la loadDatafunció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


1
No veo una diferencia con las otras soluciones, excepto que la suya accede nativeElementdirectamente 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.
Günter Zöchbauer

1
Así no es como funciona Angular2. Angular procesa primero el HTML que agrega a las plantillas de los componentes de Angular2 y solo luego lo agrega al DOM. ¿Realmente experimentaste problemas con [innerHTML]cadenas grandes en Angular2?
Günter Zöchbauer

1
Creo que esto debería informarse como error. Gracias por publicar tu resultado.
Günter Zöchbauer

25
[innerHtml]elimina el estilo codificado en el HTML. Para integrar un editor wysiwyg, tuve que usar el enfoque que se detalla aquí.
Jony Adamit

2
Para mí, esta solución funcionó para incluir un documento SVG en línea, mientras que el [innerHTML]enfoque no lo hizo.
Jared Phelps el

54

En angular2@2.0.0-alpha.44:

El enlace HTML no funcionará cuando use un {{interpolation}}, use una "Expresión" en su lugar:

inválido

<p [innerHTML]="{{item.anleser}}"></p>

-> arroja un error (Interpolación en lugar de Expresión esperada)

correcto

<p [innerHTML]="item.anleser"></p>

-> esta es la forma correcta.

Puede agregar elementos adicionales a la expresión, como:

<p [innerHTML]="'<b>'+item.anleser+'</b>'"></p>

insinuación

Angular agregará usando [innerHTML](o agregado dinámicamente por otros medios como element.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?


1
Editado después de probar de nuevo. Solución encontrada :)
jvoigt

3
El tercer ejemplo no funciona. La expresión no se evalúa. El resultado es simplemente una cadena ... ¿Hay alguna otra forma de combinar TrustedHTML con otros elementos de etiquetas?
Kévin Vilela Pinto

25

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:

import { Directive, ElementRef, Input, OnChanges, Sanitizer, SecurityContext,
  SimpleChanges } from '@angular/core';

// Sets the element's innerHTML to a sanitized version of [safeHtml]
@Directive({ selector: '[safeHtml]' })
export class HtmlDirective implements OnChanges {
  @Input() safeHtml: string;

  constructor(private elementRef: ElementRef, private sanitizer: Sanitizer) {}

  ngOnChanges(changes: SimpleChanges): any {
    if ('safeHtml' in changes) {
      this.elementRef.nativeElement.innerHTML =
        this.sanitizer.sanitize(SecurityContext.HTML, this.safeHtml);
    }
  }
}

Para ser utilizado

<div [safeHtml]="myVal"></div>

Intenté usar esto, pero recibo el siguiente error Can't bind to 'safeHtml' since it isn't a known property of 'div'. ng-version 2.4.4
LearnToday

1
@ObasiObenyOj todavía puede hacerlo sin el uso de una directiva separada si es un caso limitado, constructor( private sanitizer: Sanitizer) {} y vincular el resultado a lo que necesite, también el uso de ElementRef no está sugerido.
Vale Steve

22

Consulte otras respuestas que están más actualizadas.

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


La forma correcta es sin {{}}: <div innerHTML = "myVal"> </div>
Christian Benseler

2
Utilice la sintaxis de enlace [propiedad] en lugar de la {{interpolación}}
superluminary

Esta es definitivamente la forma incorrecta de hacerlo y debe ser rechazada. ¡Esto representará todo tu html dentro del atributo div!
AsGoodAsItGets

11

Solo para obtener una respuesta completa, si su contenido html está en una variable componente, también puede usar:

<div [innerHTML]=componementVariableThatHasTheHtml></div>

10

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


28
Definitivamente, hay casos de uso en los que desea buscar y mostrar html sin formato. Por ejemplo, buscar un artículo formateado desde un control remoto.
Alexander Chen

2
Otro escenario a menudo ignorado es proteger la lógica de negocios en la plantilla, a veces no desea que los usuarios no autorizados vean la lógica que está utilizando para mostrar la información, por lo que prefiere preparar la vista en el lado del servidor
Ayyash

2
Además, mostrar un correo electrónico HTML, por ejemplo, ¡punto / pregunta justos!
un darren

2
Si se está perdiendo el punto (que parece ser por su propia admisión), ¿por qué publicar una respuesta? Obviamente, el objetivo de Angular es utilizar su motor de vista para enlazar y representar los datos. Pero teniendo en cuenta el hecho de que hay innumerables aplicaciones en las que se puede usar una aplicación Angular, en realidad es factible que una o dos de ellas tengan el requisito de que algunos de los datos que deben mostrarse en su aplicación ya estén formateados en HTML, y podría suceder que el desarrollador no tenga control sobre ese contenido. En otras palabras ... pregunta relevante.
Gregor

Ya deberíamos abandonar Angular y usar JQuery porque Jquery hace esto mejor ...
Simon_Weaver

9

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 DomSanitizerpara marcar el contenido como seguro con bypassSecurityTrustXXXmétodos. También hay sugerencias para usar tubería para hacer eso y esa tubería a menudo se llama safeHtml.

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:

<div [innerHtml]="value | dompurify"></div>

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:

import {NgModule, ɵ_sanitizeStyle} from '@angular/core';
import {SANITIZE_STYLE} from '@tinkoff/ng-dompurify';

@NgModule({
    // ...
    providers: [
        {
            provide: SANITIZE_STYLE,
            useValue: ɵ_sanitizeStyle,
        },
    ],
    // ...
})
export class AppModule {}

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.


5

Simplemente use el [innerHTML]atributo en su HTML , algo como esto a continuación:

<div [innerHTML]="myVal"></div>

¿Alguna vez ha tenido propiedades en su componente que contienen algunas marcas html o entidades que necesita mostrar en su plantilla? La interpolación tradicional no funcionará, pero el enlace de propiedad innerHTML viene al rescate.

¡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:

<strong>Stackoverflow</strong> is <em>helpful!</em>

pero el uso [innerHTML]="myVal"hace que el resultado sea el esperado de esta manera:

¡Stackoverflow es útil!


¿Cómo mostrarías tu contenido si lo deseas sin ese contenedor div? ¿Es eso posible?
Ε Г И І И О

3

Puede aplicar varias canalizaciones para estilo, enlace y HTML como se indica en .html

<div [innerHTML]="announcementContent | safeUrl| safeHtml">
                    </div>

y en la tubería .ts para el desinfectante 'URL'

import { Component, Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({ name: 'safeUrl' })
export class SafeUrlPipe implements PipeTransform {
    constructor(private sanitizer: DomSanitizer) {}
    transform(url) {
        return this.sanitizer.bypassSecurityTrustResourceUrl(url);
    }
}

tubería para desinfectante 'HTML'

import { Component, Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';

@Pipe({
    name: 'safeHtml'
})
export class SafeHtmlPipe implements PipeTransform {
    constructor(private sanitized: DomSanitizer) {}
    transform(value) {
        return this.sanitized.bypassSecurityTrustHtml(value);
    }
}

esto se aplicará sin perturbar ningún estilo y evento de clic de enlace


2

 <div [innerHTML]="HtmlPrint"></div><br>

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.


1

En Angular 2 puedes hacer 3 tipos de enlaces:

  • [property]="expression"-> Cualquier propiedad html puede vincularse a una
    expresió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í


0

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

import { Directive, ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[appInject]'
})
export class InjectDirective {

  constructor(public viewContainerRef: ViewContainerRef) { }

}

Luego, en la plantilla donde desea inyectar el componente:

HTML

<div class="where_you_want_to_inject">    
  <ng-template appInject></ng-template>
</div>

Luego, desde el código del componente inyectado, inyectará el componente que contiene el HTML que desea:

import { Component, OnInit, ViewChild, ComponentFactoryResolver } from '@angular/core';
import { InjectDirective } from '../inject.directive';
import { InjectedComponent } from '../injected/injected.component';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.css']
})
export class ParentComponent implements OnInit {

  @ViewChild(InjectDirective) injectComp: InjectDirective;

  constructor(private _componentFactoryResolver: ComponentFactoryResolver) {
  }

  ngOnInit() {
  }

  public addComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.createComponent(componentFactory);
  }

  public removeComp() {
    const componentFactory = this._componentFactoryResolver.resolveComponentFactory(InjectedComponent);
    const viewContainerRef = this.injectComp.viewContainerRef;
    const componentRef = viewContainerRef.remove();
  }

}

Agregué una aplicación de demostración completamente funcional en Angular 2 para agregar componentes dinámicamente a la demostración DOM


0

Puede usar varios enfoques para lograr la solución. Como ya se dijo en la respuesta aprobada, puede usar:

<div [innerHTML]="myVal"></div>

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

<div id="test"></test>

Componente

var p = document.getElementsById("test");
p.outerHTML = myVal;

Enlace de propiedad

Javascript DOM HTML externo


Independientemente de si las operaciones DOM son más lentas que angulares o no, hacerlo usando getElementsByIdcualquier 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).
Aviad P.

Además, se realiza completamente fuera de cualquier zona angular, por lo que los cambios no se recogerán.
Philipp Meissner

0

Siempre podemos pasar contenido html a la innerHTMLpropiedad 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 a innerHTMLnosotros, siempre debemos asegurarnos de que el contenido esté desinfectado (usando DOMSanitizer) para que podamos escapar de todo el contenido malicioso.

Prueba debajo de la tubería:

import { Pipe, PipeTransform } from "@angular/core";
import { DomSanitizer } from "@angular/platform-browser";

@Pipe({name: 'safeHtml'})
export class SafeHtmlPipe implements PipeTransform {
    constructor(private sanitized: DomSanitizer) {
    }
    transform(value: string) {
        return this.sanitized.bypassSecurityTrustHtml(value);
    }
}

Usage:
<div [innerHTML]="content | safeHtml"></div>

Esto es necesario incluso cuando creas que no lo es. Por ejemplo, style: background-colortodas las cosas se pueden quitar y, por lo tanto, es mejor comenzar a usar esto desde el principio o se confundirá más tarde.
Simon_Weaver

Lo que entiendo es que este script es para permitir todo el contenido malicioso (bypassSecurityTrustHtml), ya que señala esto, creo que esta tubería no es necesaria a menos que confíe en la fuente. referto
Sae

0

Si desea eso en Angular 2 o Angular 4 y también desea mantener CSS en línea, puede usar

<div [innerHTML]="theHtmlString | keepHtml"></div>

Esto me dio un error `No capturado (en promesa): Error: Errores de análisis de plantilla: No se pudo encontrar la tubería 'keepHtml' '
Praveen

importar {Pipe, PipeTransform} desde "@ angular / core";
Jay Momaya


0

Trabajando en Angular v2.1.1

<div [innerHTML]="variable or htmlString">
</div>

2
Esto produce: <div _ngcontent-luf-0=""></div>para mí. El divesta vacio.
Scott Marcus el

-2

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


A veces es necesario obtener HTML del lado del servidor cuando se trata de la API antigua como en SOAP. Estaba trabajando en uno de mis proyectos con BSC (Bharat Stock Exchange) y me devolvieron el código HTML de la página del banco mientras realizaban los pagos. Por lo tanto, no puede cambiar su API, debe actualizar su código en consecuencia.
Mahendra Waykos

Podría escribir un middleware que consulta con frecuencia la API de jabón y proporcionar los resultados extraídos en un socket, por ejemplo. Consumir y extraer información a través del jabón puede ser un dolor.
Guntram

El caso de uso obvio realmente grande para el marcado sin formato es cuando su marcado proviene de un CMS y está escrito en un editor WYSIWYG. Es posible que esté sirviendo múltiples puntos finales desde un CMS sin cabeza, por ejemplo. Este tipo de cosas es la razón por la cual cada motor de plantillas tiene una opción para el marcado sin formato.
gburton
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.