2

Is there a way to add components to the declarations and entryComponents attribute dynamically (Angular 4, angular/cli 1.1.2)?

Background: I created an AppInfo.ts where developers can define additional components that will be loaded dynamically using ComponentFactoryResolver (something like widgets). This AppInfo.ts consists of an static array of components (AppInfo.components) .

How can I push elements of this array to the NgModule Decorator?

I got this solution that does work using ng serve but not using ng build --prod:

export const ngmodule = {
  declarations: [...],
  entryComponents:[ ],
  imports: [...],
  bootstrap: [
    AppComponent
  ],
  providers: [...]
};

for (let i = 0; i < AppInfo.components.length; i++) {
  const comp = <any> AppInfo.components[i];
  ngmodule.entryComponents.push(comp);
  ngmodule.declarations.push(comp);
}

@NgModule(ngmodule)

If I try to build my app using ng build --prod I get this error:

ERROR in Cannot determine the module for class DynCompExample in /Users/x/Documents/x/src/app/x/x/DynCompExample.component.ts! Add DynCompExample to the NgModule to fix it.

But if I use ng serve It works fine.

9
  • Why not just write entryComponents:[AppInfo.components],? Commented Jun 16, 2017 at 11:18
  • I don't think you can you a const variable passed to @NgModule. The production build doesn't run the module file, but scans it to extract metadata for ahead of time compiling. Therefore it doesn't know what to do in your above code. I think it explains this in the documents. Commented Jun 16, 2017 at 11:24
  • @echonax My AppInfo.components isn't just an array of components. It's of type {name:string, component:Component}[]. I made this example easier to understand. Commented Jun 16, 2017 at 11:25
  • You can kind of do this with providers. Look at the router and forRoot as an example, but components are another issue. Since they have templates the AOT compile needs to find them, and compile the templates. Commented Jun 16, 2017 at 11:26
  • 1
    See if you can do the build with AOT turned off: ng build -prod -aot=false Commented Jun 16, 2017 at 11:36

1 Answer 1

4

What I do is export an array of components and use that in @NgModule

You can split this between internal components, and developer components.

Internal.components.ts

export const INTERNAL_COMPONENTS = [
       FooterComponent,
       HeaderComponent,
       SideBarComponent
];

Developer.components.ts

export const DEVELOPER_COMPONENTS = [
       WidgetComponent,
       CustomerComponent,
       NewFeatureComponent
];

Then you import those into your module file and use them.

import {INTERNAL_COMPONENTS} from './Internal.components.ts';
import {DEVELOPER_COMPONENTS} from './Developer.components.ts';

@NgModule({
    declarations: [
        INTERNAL_COMPONENTS,
        DEVELOPER_COMPONENTS
    ],
    exports: [
        INTERNAL_COMPONENTS,
        DEVELOPER_COMPONENTS
    ]
})
export class AppModule {

}

Leave the entry component as a single main component.

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

Comments

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.