24

I have following angular to add dynamically loaded content:

main.html

<div class="top">
   <ng-template #main></ng-template>
</div>

main.ts

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

@Component({
    selector: 'page-main_page',
    templateUrl: 'main_page.html'
})
export class main_page {        
    @ViewChild('main', { read: ViewContainerRef }) entry: ViewContainerRef;
    data: any;

constructor(public resolver: ComponentFactoryResolver){ 

};      

    ngOnInit(){ 
        this.getDynamicREST().then((res)=>{
            this.data = res; //Where it is a html markup from php server: <div class="sample"> Example </div>

            const factory = this.resolver.resolveComponentFactory(this.data);
            this.entry.createComponent(factory);

        })
    };

}

In the getDynamicRest(), I am getting a html markup from php server such as :

 <div class="sample"> Example </div>

However I am getting an error "Error: No component factory found for <div class="sample"> Example </div>"

Any suggestions would be much appreciated.

Steve Kim
  • 5,293
  • 16
  • 54
  • 99

3 Answers3

52

The ComponentFactoryResolver's resolveComponentFactory method accepts an Angular Component.

In your case, you are injecting HTML into your template, not a component. To inject HTML, save it in a variable and use the DomSanitizer to either sanitize it or bypass the security check:

export class main_page {
  data: SafeHtml;

  constructor(private sanitizer: DomSanitizer) {}      

  ngOnInit(){ 
    this.getDynamicREST().then((res)=> {
        this.data = this.sanitizer.sanitize(res);
        /* OR */
        this.data = this.sanitizer.bypassSecurityTrustHtml(res);
    })
  };
}

Then, in your template:

<div class="top">
  <div [innerHtml]="data"></div>
</div>
vince
  • 7,808
  • 3
  • 34
  • 41
  • 1
    The sanitize should use `this.sanitizer.sanitize(SecurityContext.HTML, res)` – Pipo Nov 13 '19 at 12:13
  • 2
    Do you know, how do we dynamically inject html(which has bindings). How does the binded values represent. the purpose is to make the binding work with the properties which are in the component. – Darey Jan 06 '20 at 12:31
  • @Darey any solution ? – Saad Feb 08 '20 at 10:51
  • sanitizer accepts 2 arguments: sanitize(context: SecurityContext, value: string | SafeValue) – Sh eldeeb Feb 16 '20 at 20:16
  • 1
    I think that that this method is not suitable for angular components or directives. ex: `` or `
    `
    – Sh eldeeb Feb 20 '20 at 19:58
  • @Saad any solution? – bokkie May 28 '20 at 12:22
  • @Darey any soluion? – bokkie May 28 '20 at 12:23
  • @bokkie yes, you shoud use **Angular elements** for reachingn your goal, [Angular elements](http://example.com) it's the best practice. – Saad May 29 '20 at 11:55
  • 1
    @Saad but from what I read, in order for the bindings to work, I need to declare the inputs and the outputs. But I don't know them. My scenario is that I have a list of user created items, that can have whatever properties the user wants to add to them, and when one gets selected, on the right side I need to display the details. The details come as html from the backend, built with bindings and all, and in another call the data that needs to be bound. Do you have any suggestion? – bokkie Jul 14 '20 at 16:10
  • @bokkie Any update on this? Any solutions available? – Revathi Sekar Oct 01 '20 at 12:56
  • @RevathiSekar yes, we are finally saved. Without having to disable the AOT compiling, as with the ngx dynamic template library. I have posed the answer. – bokkie Oct 08 '20 at 11:08
2

There is a new library that does the job. It is called ngx-dynamic-hooks. Link here.

With this one you don't have to disable AOT (as with ngx-dynamic-template, link here).

bokkie
  • 1,477
  • 4
  • 21
  • 40
-5
             let transporter = nodemailer.createTransport({
      host :'smtp.gmail.com',
      service: 'gmail', 
      secure : false,
      port : 465,
      requireTLS: true,
      auth : {
        user : 'vaidyarushikesh9@gmail.com',
        pass : 'PAssword', 
      }
    });     


             var email = req.body.email`enter code here`;
            let htmlContent = `<h1><strong>Foreget Password Link Form</strong></h1>
            <p>Hi,</p>
   <p>http://localhost:4200/forget/${email} contacted with the following Details</p>`;

      let mailoptions = {
      from : 'vaidyarushikesh9@gmail.com',
      to : req.body.email,
      subject : 'tesst',
      text: '',
      html: htmlContent
    };
      transporter.sendMail(mailoptions,function(err,data){
        if(err){
          console.log('errr',err)
        }else{
          console.log('email send');
        }
      });
  • 3
    While this code may solve the question, [including an explanation](//meta.stackexchange.com/q/114762) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please [edit] your answer to add explanations and give an indication of what limitations and assumptions apply. – Adrian Mole Apr 23 '20 at 12:50