1

I'm trying to build an editor which will work on custom html pages. So I need to load in my Angular custom html code.

I'm desperately seeking a way to load a component with a different TemplateUrl each time. I tried to look at ComponentFactoryResolver or at ngComponentOutlet but in vain.

I also tried to do it with innerHtml but my custom code in it wasn't compiled by Angular, so that's mean that no directive wouldn't be binded.

Does anyone have a solution ?

I'm using the latest version of Angular (4).

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
rmnng
  • 59
  • 7
  • Always check doc: https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html – wannadream May 17 '17 at 19:43
  • http://stackoverflow.com/questions/40060498/angular-2-1-0-create-child-component-on-the-fly-dynamically/40080290#40080290 – yurzui May 17 '17 at 19:51
  • Like I said in my post, I already tried ComponentFactoryResolver and it didn't help, but thank you :) – rmnng May 17 '17 at 19:51
  • You actually need to create a module and component and compile during runtime with - `compileModuleAndAllComponentsAsync`. This guy made a service for it - https://github.com/patrikx3/angular-compile – Dylan May 17 '17 at 21:37
  • Thank you yurzui and Dylan. I tried both of your solutions and it seems to load well my content. But I still have an issue with it, I have a directive which is supposed to be binded on the content I load but nothing happens... – rmnng May 18 '17 at 16:51

2 Answers2

0

There is a nice article on angular website on this:

https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html

Just that, everything will remain same for the new declaration of component, just you need to make an additional entry in entryComponent for each new component added in the same module file where the new component is declared:

entryComponents: [ HeroJobAdComponent, HeroProfileComponent ],

and then using ComponentFactoryResolver you can dynamically load that component. Please let me know if you need further help.

Lambo14
  • 231
  • 1
  • 6
  • Thank you for your help but I already use this and unfortunately it doesn't solve my problem. What I need is to call dynamically an infinity of templates, I can't list them all. – rmnng May 17 '17 at 19:48
  • even if you list infinity of templates, declaration is most... along with declaration, a entry is to be made in entry component in same module.. For now don't know of any other approach to load component dynamically... do let us know if you get any other solution, will love to know it. – Lambo14 May 17 '17 at 20:18
0

Ok, I did it. Everything seems to work well.

So I use compileModuleAndAllComponentsAsync (like it's done here: https://github.com/patrikx3/angular-compile).

And to make my components and directives bindable in the compiled elements I simply had them in the declarations of the NgModule I create to compile my elements.

private async createFactory(opts: CompileOptions) {
  const cacheKey = opts.template;

   if (Object.keys(cache).indexOf(cacheKey) > -1) {
     return cache[cacheKey];
   }
   cache[cacheKey] = new Promise(async(resolve) => {
     @Component({
        template: opts.template
     })
     class TemplateComponent {
        context: any
     }
     @NgModule({
        imports: opts.imports,
        declarations: [
          TemplateComponent
          // <== Insert your directives and components here
        ]
     })
     class TemplateModule {
     }
     const component = await this.compiler.compileModuleAndAllComponentsAsync(TemplateModule);
     const factory = component.componentFactories.find((comp) =>
       comp.componentType === TemplateComponent
     );
     if (opts.onCompiled) {
       opts.onCompiled(component);
     }
     cache[cacheKey] = factory;

     resolve(factory);
  })
  return cache[cacheKey];
}

Thank you everyone!

rmnng
  • 59
  • 7