2

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>
4
  • Why don't you use a component for such an operation. Commented Jan 7, 2021 at 6: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 Commented Jan 7, 2021 at 8:52
  • can you modifire static body string or they came somewhere ? Commented Jan 7, 2021 at 9: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 Commented Jan 7, 2021 at 10:04

1 Answer 1

6

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

Sign up to request clarification or add additional context in comments.

1 Comment

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!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.