1

In Angular 9+ I can successfully convert a string to a html and then load that that html using innerHtml and bypassSecurityTrustHtml().

My question is it possible to also dynamically load/render the converted html to include and recognise angular/javascript markup language eg *ngIf, handle bars and click events.

Below is the code and stackblitz at the attempt so far but as you can see it doesn't recognise the markup.

https://stackblitz.com/edit/dynamic-angular?file=app/app.component.ts

export class AppComponent implements OnInit {
  text: string = "Hello world";
  content: any;
  constructor(private domSantizer: DomSanitizer) {}

  ngOnInit() {
    let body: any =
      '<div>{{text}}<div><br><button (click)="test()">Test</button>';
    this.content = this.domSantizer.bypassSecurityTrustHtml(body);
  }

  test() {
    alert("It works");
  }
}

Html

<div [innerHTML]="content"></div>
Ka Tech
  • 8,937
  • 14
  • 53
  • 78
  • Why don't you use a component for such an operation. – errorau Jan 07 '21 at 06:58
  • It needs to be dynamic we have a platform where are looking to implement custom style homepage to be stored as a string in db. If there is a way to attach the template to a component in runtime that would work but so far I think this is not possible – Ka Tech Jan 07 '21 at 08:52
  • can you modifire static body string or they came somewhere ? – errorau Jan 07 '21 at 09:10
  • the string will be coming from an API retrieving from a database. Nb: The data itself will be secured as it is only set by admin hence no issue with XSS – Ka Tech Jan 07 '21 at 10:04

1 Answers1

4

I have researched and tried many solutions. My research and trial results are below.

html

<div #container></div>

typescript side as below

export class AppComponent implements OnInit {
  @ViewChild("container", { read: ViewContainerRef })
  container: ViewContainerRef;
  constructor(private compiler: Compiler) {}
  text: string = "asdasd";
  ngOnInit() {
    this.addComponent(
      `<div>{{text}}<div><br><button (click)="test()">Test</button>
       `,
      {
        text: "Hello word",
        test: function() {
          alert("It's work");
        }
      }
    );
  }

  private addComponent(template: string, properties?: any = {}) {
    @Component({ template })
    class TemplateComponent {}

    @NgModule({ declarations: [TemplateComponent] })
    class TemplateModule {}

    const mod = this.compiler.compileModuleAndAllComponentsSync(TemplateModule);
    const factory = mod.componentFactories.find(
      comp => comp.componentType === TemplateComponent
    );
    const component = this.container.createComponent(factory);
    Object.assign(component.instance, properties);
    // If properties are changed at a later stage, the change detection
    // may need to be triggered manually:
    // component.changeDetectorRef.detectChanges();
  }

demo

some posts I have reviewed

compile dynamic Component

angular-html-binding

I think it makes the most sense :)

errorau
  • 2,121
  • 1
  • 14
  • 38
  • Wow I really didn't think this was possible. It works well thank you so much for taking the time and doing this, absolute legend! – Ka Tech Jan 07 '21 at 11:05