Reputation: 2149
I have this in my app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { HttpModule, Http } from '@angular/http';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { EliteApi } from '../shared/shared';
import { MyApp } from './app.component';
import { MyTeams, Tournaments, TeamDetails, Teams, TeamHome, Standings } from '../pages/pages';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
@NgModule({
declarations: [
MyApp,
MyTeams,
TeamDetails,
Tournaments,
Teams,
TeamHome,
Standings
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp),
HttpModule
],
bootstrap: [IonicApp],
entryComponents: [
MyApp,
MyTeams,
TeamDetails,
Tournaments,
Teams,
TeamHome,
Standings
],
providers: [
HttpModule,
StatusBar,
SplashScreen,
{ provide: ErrorHandler, useClass: IonicErrorHandler },
EliteApi
]
})
export class AppModule { }
At the moment my declarations
and entryComponents
both are exactly the same. They contain all of the page/components that I built for my app. If I remove any entry from any of the properties I get error in angular2.
My question is if they are always the same then what is the need for these properties? I think I am definitely missing some point here. When would entryComponents and declaractions be different from one another?
Upvotes: 74
Views: 45312
Reputation: 1016
For this you need to understand how angular actually works behind the scenes when it comes to creating components.
Any component as well as directives and pipes you plan on working with, you need to add them to your declarations
array in @NgModule
of app.module.ts
(while working with multiple modules
, we import the feature module in our app.module.ts
imports
array, and that feature module
has all the components in its declarations
array).
The above mentioned step is important for angular to understand what's a component or which components and directives you have in your app because, it does not automatically scan all your files. You'd need to tell it which components exist, after creating a new component.
Still this alone only makes angular aware of it so that it is able to create such a component when it finds it in one of two places--
The first place would be in your templates if in your templates angular finds a selector
of a component-->
then it basically looks into the declarations
array for that particular component-->
finds that there and then is able to create that component.
The other place where angular will look for this component is in your routs
in your rout config
,-->
when you point at a component there angular will also check that in the declarations
array and-->
if it finds that there it is able to create such a component and load it.
Now one place that does not work by default is when you want to create a component manually in code. Like when you want to create a dynamic component
with component factory
like an alert component
maybe which only shows up when there is any error and you neither mention the selector
of it in any template
nor in the rout config
.
And now, here angular does not automatically reach out to the declarations array. It simply doesn't do that. You can complain about that. Still it's the case.
You instead deliberately need to inform angular that in this case the alert component will need to be created at some place and that angular basically should be prepared for this.
Generally angular will prepare itself for this creation when it finds a component in the template
or in a rout config
.But in our case as we haven't done either of the two things as mentioned above, angular won't do prepare itself.
Now to tell angular to be prepared for the creation of that component you need to add a special property to the object you pass to Ngmodule
besides declarations
import
and so on.
That property is entry components
, it is an array of component types, but only those components that will eventually be created without routs
or selectors
.
But with the launch of Angular 9, there were changes made behind the scenes, and it does all these work for you, you do not need to mention the entry components
manually anymore.
Credits--Learned these concepts from the Udemy course "Angular the Complete Guide" -by Maximilian Schwarzmüller .
Upvotes: 1
Reputation: 17514
Adding to what @Julia has answered to this question. I would like to add use case of Modal.
Lets say, you have a component called as ModalComponent
. To make it more reusable, you would like to pass a component name and expect that component to be rendered inside the ModalComponent
*.
Sample module.ts
would be something like:
import:[ModalModule], // As a best practice, we can create Modal as a separate Feature
entryComponent : [TheCompYouWantToRenderInsideModalComponent]
We would pass TheCompYouWantToRenderInsideModalComponent
as entryComponent
because this component will not be present while writing the website code (i.e there would not be selector of TheCompYouWantToRenderInsideModalComponent
in any HTML
file). We will pass this component
to Modal and then it'll be rendered dynamically as and when the modal is opened. Something like below:
onSomeButtonClickToOpenModal(){
this.modalService.openModal(TheCompYouWantToRenderInsideModalComponent);
}
*In the ModalModule
, we would create service to use ComponentFactoryResolver
and take TheCompYouWantToRenderInsideModalComponent
as argument. Later, we can call a function (call it openModal(componentType: ComponentType)
) which will Open & render using ComponentFactoryResolver
Side Note: The entryComponent
will also play an important part in Angular V6 elements
feature for the same purpose.
Update: Angular 9
With Angular 9
being released, we no more need to have entryComponent
, Thanks to Ivy compiler
Upvotes: 35
Reputation: 21367
for Angular 9 or Angular 8 with Ivy explicitly enabled
Entry Components With Ivy is not required anymore and and now deprecated
Upvotes: 4
Reputation: 159
An entry component is any component that Angular loads imperatively, which means you’re not referencing it in the template, by type. For Example :
@Component({
selector: 'app-entry-component', // <== component select tags
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppEntryComponent {
// <== Component Class
}
add this selector in the component you are using
<app-entry-component></app-entry-component>
add this component in appmodule
const routes: Routes = [
{
path: '',
component: ComponentClassName,
children: []
}
]
finally
@NgModule({
declarations: [
AppComponent
],
imports: [
...
],
providers: [],
bootstrap: [AppComponent],
entryComponents: [
AppEntryComponent
]
})
export class AppModule { }
Upvotes: 0
Reputation: 7250
In short:
The "real" reason behind the existence of entryComponents
is tree-shaking, while declarations
exists mainly for module encapsulation. So they aren't even comparable. If tree-shaking wasn't our concern, we would be good with declarations as a single source for both.
Longer answer
All the components
that you created in your module
don't go to final bundle. Rather, only the components which were declared in template
using selectors
OR the components
that were added to entryComponents
array (by you or the framework).
You would want to add the component when you creating the component dynamically like using ComponentFactoryResolver
as stated by accepted answer. Or framework can add the component when you declare them in Route array or during other imperative creation.
From official docs:
In fact, many libraries declare and export components you'll never use. For example, a material design library will export all components because it doesn’t know which ones you will use. However, it is unlikely that you will use them all. For the ones you don't reference, the tree shaker drops these components from the final code package.
If a component isn't an entry component and isn't found in a template, the tree shaker will throw it away. So, it's best to add only the components that are truly entry components to help keep your app as trim as possible.
Upvotes: 5
Reputation: 17889
The entryComponents
array is used to define only components that are not found in html and created dynamically with ComponentFactoryResolver
. Angular needs this hint to find them and compile. All other components should just be listed in the declarations array.
Here's the documentation on angular site
Upvotes: 125