What is entryComponents in angular ngModule?
Asked Answered
T

7

164

I am working on an Ionic app ( 2.0.0-rc0 ) which depends on angular 2 . So the new introduction of ngModules is included. I am adding my app.module.ts. below.

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { Users } from '../pages/users/users';

@NgModule({
  declarations: [
    MyApp,
    Users
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    Users
  ]
})
export class AppModule {}

What does entryComponents do here? Components are already defined in declarations . So what's the need of repeating them ? What would happen if I dont include a component here?

Trophoblast answered 28/9, 2016 at 19:35 Comment(1)
Angular uses entryComponents to enable "tree shaking" i.e. only compiling the components that are actually used in the project instead of compiling all the components that are declared in ngModule but are never used. angular.io/docs/ts/latest/cookbook/…entrycomponents-Snooty
B
188

Note: EntryComponent is Deprecated from Angular 9.0.0 See the angular docs form more details.

This is for dynamically added components that are added using ViewContainerRef.createComponent(). Adding them to entryComponents tells the offline template compiler to compile them and create factories for them.

The components registered in route configurations are added automatically to entryComponents as well because router-outlet also uses ViewContainerRef.createComponent() to add routed components to the DOM.

Offline template compiler (OTC) only builds components that are actually used. If components aren't used in templates directly the OTC can't know whether they need to be compiled. With entryComponents you can tell the OTC to also compile these components, so they are available at runtime.

What is an entry component? (angular.io)

NgModule docs (angular.io)

Defines the components that should be compiled as well when this component is defined. For each components listed here, Angular will create a ComponentFactory and store it in the ComponentFactoryResolver.

If you don't list a dynamically added component to entryComponents you'll get an error message a bout a missing factory because Angular won't have created one.

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

Briar answered 28/9, 2016 at 19:37 Comment(11)
frankly speaking, I know its 100% correct answer but went bouncer for me, could you please elaborate more?Coronary
Hard to tell what's unclear. Offline template compiler (OTC) only builds components that are actually used. If components aren't used in templates directly the OTC can't know whether they need to be compiled. With entryComponents you can tell the OTC to also compile this components so they are available at runtime.Tie
Thanks Gunter . Can you give me a scenario in which not adding components in entryComponents would cause some issue?Trophoblast
#36325712 would be such an exampleTie
So in general, if component is listed in declarations it should also be listed in entryComponents, right?Nathalienathan
only if a component is added dynamically with createComponent in your code or for example the router that also uses thod API to add components.Tie
Do I need entryComponent if I always use JIT compiler?Lecroy
I'm pretty sure you do because it's also required in Plunker AFAIR. Should be pretty easy to find out I guess.Tie
My list of such components in ionic2 app is quite big so I made a concat of entryComponents for declarations: let declarations = entryComponents.concat([ additionalDeclarations, ... ]);Priscillaprise
entryComponents is deprecated from Angular version 9 see my answer further down for more information https://mcmap.net/q/149457/-what-is-entrycomponents-in-angular-ngmoduleCasta
I end up at StackOverflow questions/answers like this when I'm trying to do something like in Angular 16 days run a sample that was written in Angular 9. I needed to redo package.json to 16.0.0 entries instead of 9.0.0 to get rid of some errors. Then I got "'entryComponents' does not exist in type 'NgModule'". The offending line was in main.ts and simply eliminating the "entryComponents: [TheSpecificClassInTheDemoApp]," line resolved the error and the app ran.Rubbish
A
64

The other answers mention this but the basic summary is:

  • It's needed when a Component is NOT used in the html , ex: <my-component />
  • For example with Angular Material Dialogs you use them indirectly, they are created inside the TS code and not the html:
openDialog() {
    const dialogRef = this.dialog.open(MyExampleDialog, { width: '250px'});
}

This requires you to register it as an entryComponent:

  • entryComponents: [MyExampleDialog]

Otherwise you get a error:

  • ERROR Error: No component factory found for MyExampleDialog. Did you add it to @NgModule.entryComponents?
Atwell answered 3/1, 2019 at 15:30 Comment(3)
The best explanation over here.Smallminded
Simple, thank you. XDMidwifery
Sometimes the simplest answer tends to be the best one.Quinlan
O
34

You won't get explanation better than Angular docs: entry-components and ngmodule-faq.

And below is the explanation from the angular docs.

An entry component is any component that Angular loads imperatively by type.

A component loaded declaratively via its selector is not an entry component.

Most application components are loaded declaratively. Angular uses the component's selector to locate the element in the template. It then creates the HTML representation of the component and inserts it into the DOM at the selected element. These aren't entry components.

A few components are only loaded dynamically and are never referenced in a component template.

The bootstrapped root AppComponent is an entry component. True, its selector matches an element tag in index.html. But index.html isn't a component template and the AppComponent selector doesn't match an element in any component template.

Angular loads AppComponent dynamically because it's either listed by type in @NgModule.bootstrap or boostrapped imperatively with the module's ngDoBootstrap method.

Components in route definitions are also entry components. A route definition refers to a component by its type. The router ignores a routed component's selector (if it even has one) and loads the component dynamically into a RouterOutlet.

The compiler can't discover these entry components by looking for them in other component templates. You must tell it about them by adding them to the entryComponents list.

Angular automatically adds the following types of components to the module's entryComponents:

  • The component in the @NgModule.bootstrap list.
  • Components referenced in router configuration.

You don't have to mention these components explicitly, although doing so is harmless.

Organism answered 8/3, 2017 at 19:1 Comment(4)
Right now the angular docs are not available, so thank SO for that!Rigorism
This doesn't seem to mention that components in route configurations are automatically added to entryComponents (so you usually never need to define it).Kreis
If we create a component to be used as an EntryComponent should we remove the selector attribute? (since it won't be used)Pinfeather
Best answer for a newbieDraughty
C
12

As of Angular 9 entryComponents is no longer required thanks to Ivy allowing this feature to be deprecated and so can be removed from module declarations.

Deprecated APIs and features - entryComponents and ANALYZE_FOR_ENTRY_COMPONENTS no longer required

Previously, the entryComponents array in the NgModule definition was used to tell the compiler which components would be created and inserted dynamically. With Ivy, this isn't a requirement anymore and the entryComponents array can be removed from existing module declarations. The same applies to the ANALYZE_FOR_ENTRY_COMPONENTS injection token.

Angular Ivy

Ivy is the code name for Angular's next-generation compilation and rendering pipeline. With the version 9 release of Angular, the new compiler and runtime instructions are used by default instead of the older compiler and runtime, known as View Engine.

Casta answered 17/7, 2020 at 3:22 Comment(1)
Doesn't answers the question but it's still an informative answer. +1.Altigraph
N
6

The entryComponents array is used to define only components that are not found in html and created dynamically. Angular requires this hint to find entry component and compile them.

There are two main types of entry components:

  • The bootstrapped root component.
  • A component you specify in a route definition.

For more detailed information around entry components, please refer angular.io https://angular.io/guide/entry-components

Nitid answered 3/1, 2019 at 16:0 Comment(0)
J
2

A Bit of Background about entryComponent

entryComponent is any component Angular loads imperatively. You can declare entryComponent by bootstrapping it in NgModule or in route definitions.

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent] // bootstrapped entry component
})

Documentation says below

To contrast the two types of components, there are components which are included in the template, which are declarative. Additionally, there are components which you load imperatively; that is, entry components.

Now to answer your specific question about entryComponents

There is entryComponents array in @NgModule file. You can use this to add entryComponents if component is bootstrapped using ViewContainerRef.createComponent().

That is you're creating components dynamically and not by bootstrapping or in template.

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(myComp.component);
const viewContainerRef = this.compHost.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent(componentFactory);
Jeter answered 6/8, 2019 at 4:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.