How to insert an HTML file with [innerHtml] and maintain the attributes of the Angular

5

In my Componente I get HTML in the form of a String and use [innerHtml] to insert this HTML into the Component View.

Component:

test(){
    alert('Teste :D');
}

html_string = '<input type="button" (click)="test()">';

View:

<div [innerHtml]="html_string"></div>

The problem I'm facing is that at the time the page loads, it ignores (click)="teste()" . At the end it ends up in the element, others that are directly in the View, at the end of the element. And I do the validation with sanitizer .

    
asked by anonymous 16.03.2018 / 23:18

2 answers

6

Update 2

If you do not want to use the library, you can use the class Compiler (Note: Do not confuse with $compile of AngularJS )

Archive app.component.ts

import { Compiler, Component, Injector, NgModule, NgModuleRef, ViewChild, ViewContainerRef } from "@angular/core";

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  @ViewChild('testando', { read: ViewContainerRef }) _container: ViewContainerRef;
  constructor(private _compiler: Compiler, private _injector: Injector, private _m: NgModuleRef<any>) { }

  test() {
    alert('Teste :D');
  }

  ngAfterViewInit() {
    const html_string = '<input type="button" (click)="test()" value={{btnValue}}>';
    const tmpCmp = Component({ template: html_string })(class { });
    const tmpModule = NgModule({ declarations: [tmpCmp] })(class { });

    this._compiler.compileModuleAndAllComponentsAsync(tmpModule)
      .then((factories) => {
        const f = factories.componentFactories[0];
        const cmpRef = f.create(this._injector, [], null, this._m);
        cmpRef.instance.btnValue = 'CLIQUE!';
        cmpRef.instance.test = this.test;
        this._container.insert(cmpRef.hostView);
      })
  }
}

Archive app.component.html

<div #testando></div>
  

See working at stackblitz

     

The example above was adapted from the article: Here is what you need to know about dynamic components in Angular . (Here's what you need to know about dynamic components in Angular - Free translation.)

Update 1

By doing a search on Google , I found the p3x-angular-compile library.

To use, just follow the steps below:

  • Import the library into the app.module.ts

    import { CompileModule} from 'p3x-angular-compile';
    
  • Configure the module:

    @NgModule({
      imports: [ ... CompileModule],
      ...
    })
    
  • Template Code:

    <div *ngIf="true" 
      [p3x-compile]="html_string"
      [p3x-compile-ctx]="this" >
    </div>
    
  • Use your component normally just like this in the question, with the exception that events must be preceded by context. :

    html_string = '<input type="button" (click)="context.test('wmsouza')" value="CLIQUE AQUI!">';
    
    test(nome) {
      alert('Olá, ${nome}');
    }
    
  •   

    You can see it working at stackblitz

    This is not possible since the subclass DomSanitizer simply ignores, the solution would be to use the addEventListener method to register an event in the element.

    import { Component, ChangeDetectorRef, ElementRef } from '@angular/core';
    import { DomSanitizer } from '@angular/platform-browser';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css']
    })
    export class AppComponent {
    
      html_string;
    
      constructor(private sanitizer: DomSanitizer, private elRef: ElementRef, private cdRef: ChangeDetectorRef) { }
    
      test = (nome) => {
        alert('Olá, ${nome}');
      }
    
      ngOnInit() {
        this.html_string = this.sanitizer.bypassSecurityTrustHtml('<input type="button" value="CLIQUE AQUI!">');
        this.cdRef.detectChanges();
        this.elRef.nativeElement.querySelector('input').addEventListener('click', _ => { this.test('wmsouza') }, false);
      }
    }
    
      

    See working at stackblitz

        
    20.03.2018 / 05:08
    0

    Very simple, use $compile :

    Put it in your app.controller :

    app.controller('MainController', function($scope, $http, $rootScope, $compile) {
    

    ...

    Make the APPEND HTML like this:

    var elementoHTML = document.getElementById("elemento");
    angular.element(elementoHTML).html( $compile(response.data)($scope) );
    
        
    23.03.2018 / 21:17