1

I tried to create a component dynamic like that:

Here is my file dynamicComponent.ts:

import {Directive, Input, ViewContainerRef, Component, ReflectiveInjector, ComponentFactory, ComponentFactoryResolver} from '@angular/core';

export function createComponentFactory(resolver: ComponentFactoryResolver, metadata: Component): Promise<ComponentFactory<any>> {
const cmpClass = class DynamicComponent {
};
const decoratedCmp = Component(metadata)(cmpClass);
return new Promise((resolve) => {
    resolve(resolver.resolveComponentFactory(decoratedCmp)); 
});
}

@Directive({
selector: 'dynamic-html-outlet'
 })
export class DynamicComponent {
@Input() src: string;

constructor(public vcRef: ViewContainerRef, public resolver:    ComponentFactoryResolver) {
}

ngOnChanges() {
    if (!this.src) return;

    const metadata = new Component({
        selector: 'dynamic-component',
        template: this.src
    });
    createComponentFactory(this.resolver, metadata)
        .then(factory => {
            const injector = ReflectiveInjector.fromResolvedProviders([],    this.vcRef.parentInjector);
            this.vcRef.createComponent(factory, 0, injector, []).changeDetectorRef.detectChanges();
        });
}
}

Here is the app.module.ts :

@NgModule({
   declarations: [
   MyApp,
   DynamicComponent,
   ...APP_PAGES,
   ...APP_DIRECTIVES 
],
imports: [
  IonicModule.forRoot(MyApp),
  NgReduxModule,
  MomentModule,
  TranslateModule.forRoot({
   provide: TranslateLoader,
   useFactory: (http: Http) => new TranslateStaticLoader(http, '../assets/i18n', '.json'),
  deps: [Http]
   })
  ],
 bootstrap: [IonicApp],
 entryComponents: [
 MyApp,
 //DynamicComponent,
 //ScrollableHeader,
 AppLink, 
 ...APP_PAGES,
 ...APP_DIRECTIVES
 ],
 providers: [
  ...APP_SERVICES
 ]
 })

The component AppLink that have to be loaded is defined Something like that:

@Component({
  selector: 'app-link',
  template: '<a (click)="openLink($event);"><ng-content></ng-content></a>',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppLink {
  @Input() link;
  //some method here
}

I got always this error:

polyfills.js:3 Unhandled Promise rejection: Template parse errors: Can't bind to 'link' since it isn't a known property of 'app-link'.

Thanks for any helps?

hqho
  • 604
  • 7
  • 9

1 Answers1

0

You need to add the components to

@NgModule({
  entryComponents: [MyDynamicComponent],
  ...
})

for component factories being created.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I added @NgModule({ entryComponents: [DynamicComponent], ... }) but I got always this error: Can't bind to 'src' since it isn't a known property of 'dynamic-html-outlet'. – hqho Oct 05 '16 at 08:59
  • Sounds like you didn't add `DynamicComponent` to `directives: []` of the module where you're using it (or in a module added to `imports: []`) – Günter Zöchbauer Oct 05 '16 at 09:05
  • You should not ad `DynamicComponent` to `entryComponents` but instead the components that you want to be added by `DynamicComponent`. `DynamicComponent` needs to go into `declarations`. – Günter Zöchbauer Oct 05 '16 at 09:06
  • I added : `DynamicComponent` to `declarations (app.module.ts)`, I added also the component `AppLink` that I want to be added by DynamicComponent. It is defined Something like: @Component({ selector: 'app-link', template: '', changeDetection: ChangeDetectionStrategy.OnPush, inputs: ['link'] }) But I got always this error: Can't bind to 'link' since it isn't a known property of 'app-link'. I tried adding @Input() link but not working – hqho Oct 05 '16 at 09:19
  • Can you please edit your question and add the code you have currently. Code in comments is unreadable. – Günter Zöchbauer Oct 05 '16 at 09:20
  • Only components that are added usong `vcRef.createComponent()` should go into `entryComponents`. Components added this way can't have bound inputs. Adding inputs is therefore redundant if the component isn't also used directly. Your code doesn't show where you bind to `link` (like `[link]="xxx"`). Can you please add that code? – Günter Zöchbauer Oct 05 '16 at 09:36
  • In fact, in my code, line "const metadata", 'this.src' is something like : . In addition, it worked using Angular2 rc4, but not with Angular2 final (I'm trying to update my app with Ionic2 RC) – hqho Oct 05 '16 at 09:44
  • I don't know about creating components dynamically at runtime. I think you should add this code as well to your question. In my opinion this is one of the more important parts of your question anyway. There are recent answers about using the compiler at runtime which should show how you do that (I didn't experiment with that yet myself). – Günter Zöchbauer Oct 05 '16 at 09:47
  • thanks for your help, it worked for me thanks to this example http://stackoverflow.com/questions/38888008/how-can-i-use-create-dynamic-template-to-compile-dynamic-component-with-angular/39912752#39912752 – hqho Oct 07 '16 at 11:59