diff --git a/aio/content/examples/ngmodule/src/app/title.component.ts b/aio/content/examples/ngmodule/src/app/title.component.ts
index 05bbb64aae..b0761208a0 100644
--- a/aio/content/examples/ngmodule/src/app/title.component.ts
+++ b/aio/content/examples/ngmodule/src/app/title.component.ts
@@ -1,18 +1,17 @@
// #docplaster
// #docregion
// #docregion v1
-import { Component, Input } from '@angular/core';
+import { Component } from '@angular/core';
// #enddocregion v1
import { UserService } from './user.service';
// #docregion v1
@Component({
selector: 'app-title',
- templateUrl: './title.component.html',
+ templateUrl: './title.component.html'
})
export class TitleComponent {
- @Input() subtitle = '';
- title = 'NgModules';
+ title = 'Angular Modules';
// #enddocregion v1
user = '';
diff --git a/aio/content/guide/aot-compiler.md b/aio/content/guide/aot-compiler.md
index e1c56e5ecb..bedec81fa0 100644
--- a/aio/content/guide/aot-compiler.md
+++ b/aio/content/guide/aot-compiler.md
@@ -409,7 +409,7 @@ function; it can only contain a single `return` statement.
The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes.
Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code")
-for these methods to see how macros can simplify configuration of complex Angular modules.
+for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodule).
### Metadata rewriting
diff --git a/aio/content/guide/dependency-injection.md b/aio/content/guide/dependency-injection.md
index 4731a2ffaf..61c351cf8d 100644
--- a/aio/content/guide/dependency-injection.md
+++ b/aio/content/guide/dependency-injection.md
@@ -160,7 +160,7 @@ Providing the `UserService` with an Angular module is a good choice.
To be precise, Angular module providers are registered with the root injector
-_unless the module is_ [lazy loaded](guide/ngmodule#lazy-load).
+_unless the module is_ [lazy loaded](guide/ngmodule#lazy-load-DI).
In this sample, all modules are _eagerly loaded_ when the application starts,
so all module providers are registered with the app's root injector.
diff --git a/aio/content/guide/ngmodule-faq.md b/aio/content/guide/ngmodule-faq.md
index 81f5386cbb..812372e82d 100644
--- a/aio/content/guide/ngmodule-faq.md
+++ b/aio/content/guide/ngmodule-faq.md
@@ -1,80 +1,60 @@
# NgModule FAQs
-NgModules help organize an application into cohesive blocks of functionality.
+**NgModules** help organize an application into cohesive blocks of functionality.
-The [NgModules](guide/ngmodule) page guides you
-from the most elementary `@NgModule` to a multi-faceted sample with lazy-loaded modules.
+The [NgModules](guide/ngmodule) guide takes you step-by-step
+from the most elementary `@NgModule` class to a multi-faceted sample with lazy-loaded modules.
This page answers the questions many developers ask about NgModule design and implementation.
-
-
-These FAQs assume that you have read the [NgModules](guide/ngmodule) page.
-
+These FAQs assume that you have read the [NgModules](guide/ngmodule) guide.
{@a q-what-to-declare}
-
-
## What classes should I add to _declarations_?
Add [declarable](guide/ngmodule-faq#q-declarable) classes—components, directives, and pipes—to a `declarations` list.
-Declare these classes in _exactly one_ module of the application.
-Declare them in _this_ module if they _belong_ to this module.
-
+Declare these classes in _exactly one_ NgModule.
+Declare them in _this_ NgModule if they _belong_ to this module.
-
-
{@a q-declarable}
-
-
## What is a _declarable_?
Declarables are the class types—components, directives, and pipes—that
-you can add to a module's `declarations` list.
+you can add to an NgModule's `declarations` list.
They're the _only_ classes that you can add to `declarations`.
-
-
-
{@a q-what-not-to-declare}
-
-
## What classes should I _not_ add to _declarations_?
-Add only [declarable](guide/ngmodule-faq#q-declarable) classes to a module's `declarations` list.
+Add only [declarable](guide/ngmodule-faq#q-declarable) classes to an NgModule's `declarations` list.
Do *not* declare the following:
-* A class that's already declared in another module, whether an app module, @NgModule, or third-party module.
-* An array of directives imported from another module.
+* A class that's already declared in another NgModule.
+* An array of directives imported from another NgModule.
For example, don't declare FORMS_DIRECTIVES from `@angular/forms`.
-* Module classes.
+* NgModule classes.
* Service classes.
* Non-Angular classes and objects, such as
strings, numbers, functions, entity models, configurations, business logic, and helper classes.
-
-
-
{@a q-why-multiple-mentions}
-
-
-## Why list the same component in multiple _NgModule_ properties?
+## Why list the same component in multiple _@NgModule_ properties?
`AppComponent` is often listed in both `declarations` and `bootstrap`.
You might see `HeroComponent` listed in `declarations`, `exports`, and `entryComponents`.
@@ -84,46 +64,42 @@ Membership in one list doesn't imply membership in another list.
* `AppComponent` could be declared in this module but not bootstrapped.
* `AppComponent` could be bootstrapped in this module but declared in a different feature module.
-* `HeroComponent` could be imported from another app module (so you can't declare it) and re-exported by this module.
+* `HeroComponent` could be imported from another application module (so you can't declare it) and re-exported by this module.
* `HeroComponent` could be exported for inclusion in an external component's template
as well as dynamically loaded in a pop-up dialog.
-
-
-
{@a q-why-cant-bind-to}
-
-
## What does "Can't bind to 'x' since it isn't a known property of 'y'" mean?
-This error usually means that you haven't declared the directive "x"
-or haven't imported the module to which "x" belongs.
+This error often means that you haven't declared the directive "x"
+or haven't imported the NgModule to which "x" belongs.
-For example, if "x" is `ngModel`, you probably haven't imported the `FormsModule` from `@angular/forms`.
+
-Perhaps you declared "x" in an application sub-module but forgot to export it?
-The "x" class isn't visible to other modules until you add it to the `exports` list.
+You also get this error if "x" really isn't a property or if "x" is a private component property (i.e., lacks the `@Input` or `@Output` decorator).
+
+
+For example, if "x" is `ngModel`, you may not have imported the `FormsModule` from `@angular/forms`.
+
+Perhaps you declared "x" in an application feature module but forgot to export it?
+The "x" class isn't visible to other components of other NgModules until you add it to the `exports` list.
-
-
{@a q-what-to-import}
-
-
## What should I import?
-Import modules whose public (exported) [declarable classes](guide/ngmodule-faq#q-declarable)
+Import NgModules whose public (exported) [declarable classes](guide/ngmodule-faq#q-declarable)
you need to reference in this module's component templates.
This always means importing `CommonModule` from `@angular/common` for access to
the Angular directives such as `NgIf` and `NgFor`.
-You can import it directly or from another module that [re-exports](guide/ngmodule-faq#q-reexport) it.
+You can import it directly or from another NgModule that [re-exports](guide/ngmodule-faq#q-reexport) it.
Import `FormsModule` from `@angular/forms`
if your components have `[(ngModel)]` two-way binding expressions.
@@ -133,15 +109,10 @@ components, directives, and pipes.
Import only [BrowserModule](guide/ngmodule-faq#q-browser-vs-common-module) in the root `AppModule`.
-
-
-
{@a q-browser-vs-common-module}
-
-
## Should I import _BrowserModule_ or _CommonModule_?
The *root application module* (`AppModule`) of almost every browser application
@@ -153,80 +124,61 @@ should import `BrowserModule` from `@angular/platform-browser`.
which means that components in the `AppModule` module also have access to
the Angular directives every app needs, such as `NgIf` and `NgFor`.
-_Do not import_ `BrowserModule` in any other module.
+_Do not import_ `BrowserModule` in any other NgModule.
*Feature modules* and *lazy-loaded modules* should import `CommonModule` instead.
They need the common directives. They don't need to re-install the app-wide providers.
-
-
`BrowserModule` throws an error if you try to lazy load a module that imports it.
-
-
Importing `CommonModule` also frees feature modules for use on _any_ target platform, not just browsers.
-
-
-
{@a q-reimport}
+## What if I import the same NgModule twice?
-
-## What if I import the same module twice?
-
-That's not a problem. When three modules all import Module 'A',
+That's not a problem. When three NgModules all import Module 'A',
Angular evaluates Module 'A' once, the first time it encounters it, and doesn't do so again.
-That's true at whatever level `A` appears in a hierarchy of imported modules.
+That's true at whatever level `A` appears in a hierarchy of imported NgModules.
When Module 'B' imports Module 'A', Module 'C' imports 'B', and Module 'D' imports `[C, B, A]`,
then 'D' triggers the evaluation of 'C', which triggers the evaluation of 'B', which evaluates 'A'.
When Angular gets to the 'B' and 'A' in 'D', they're already cached and ready to go.
-Angular doesn't like modules with circular references, so don't let Module 'A' import Module 'B', which imports Module 'A'.
-
+Angular doesn't like NgModules with circular references, so don't let Module 'A' import Module 'B', which imports Module 'A'.
-
-
{@a q-what-to-export}
-
-
## What should I export?
-Export [declarable](guide/ngmodule-faq#q-declarable) classes that components in _other_ modules
+Export [declarable](guide/ngmodule-faq#q-declarable) classes that components in _other_ NgModules
are able to reference in their templates. These are your _public_ classes.
If you don't export a class, it stays _private_, visible only to other component
-declared in this module.
+declared in this NgModule.
You _can_ export any declarable class—components, directives, and pipes—whether
-it's declared in this module or in an imported module.
-
-You _can_ re-export entire imported modules, which effectively re-exports all of their exported classes.
-A module can even export a module that it doesn't import.
+it's declared in this NgModule or in an imported NgModule.
+You _can_ re-export entire imported NgModules, which effectively re-exports all of their exported classes.
+An NgModule can even export a module that it doesn't import.
-
-
{@a q-what-not-to-export}
-
-
## What should I *not* export?
Don't export the following:
-* Private components, directives, and pipes that you need only within components declared in this module.
-If you don't want another module to see it, don't export it.
+* Private components, directives, and pipes that you need only within components declared in this NgModule.
+If you don't want another NgModule to see it, don't export it.
* Non-declarable objects such as services, functions, configurations, and entity models.
* Components that are only loaded dynamically by the router or by bootstrapping.
Such [entry components](guide/ngmodule-faq#q-entry-component-defined) can never be selected in another component's template.
@@ -235,59 +187,40 @@ While there's no harm in exporting them, there's also no benefit.
For example, there's no point in re-exporting `HttpModule` because it doesn't export anything.
It's only purpose is to add http service providers to the application as a whole.
-
-
-
{@a q-reexport}
-
-
{@a q-re-export}
-
-
-## Can I re-export classes and modules?
+## Can I re-export classes and NgModules?
Absolutely.
-Modules are a great way to selectively aggregate classes from other modules and
+NgModules are a great way to selectively aggregate classes from other NgModules and
re-export them in a consolidated, convenience module.
-A module can re-export entire modules, which effectively re-exports all of their exported classes.
-Angular's own `BrowserModule` exports a couple of modules like this:
+An NgModule can re-export entire NgModules, which effectively re-exports all of their exported classes.
+Angular's own `BrowserModule` exports a couple of NgModules like this:
exports: [CommonModule, ApplicationModule]
-
-
-
-A module can export a combination of its own declarations, selected imported classes, and imported modules.
+An NgModule can export a combination of its own declarations, selected imported classes, and imported NgModules.
-
-
Don't bother re-exporting pure service modules.
-Pure service modules don't export [declarable](guide/ngmodule-faq#q-declarable) classes that another module could use.
+Pure service modules don't export [declarable](guide/ngmodule-faq#q-declarable) classes that another NgModule could use.
For example, there's no point in re-exporting `HttpModule` because it doesn't export anything.
It's only purpose is to add http service providers to the application as a whole.
-
-
-
-
-
{@a q-for-root}
-
-
## What is the _forRoot_ method?
The `forRoot` static method is a convention that makes it easy for developers to configure the module's providers.
@@ -297,19 +230,14 @@ Apps pass a `Routes` object to `RouterModule.forRoot` in order to configure the
`RouterModule.forRoot` returns a [ModuleWithProviders](api/core/ModuleWithProviders).
You add that result to the `imports` list of the root `AppModule`.
-
-
-
-Only call and import a `.forRoot` result in the root application module, `AppModule`.
-Importing it in any other module, particularly in a lazy-loaded module,
+Only call and import a `.forRoot` result in the root application NgModule, `AppModule`.
+Importing it in any other NgModule, particularly in a lazy-loaded NgModule,
is contrary to the intent and will likely produce a runtime error.
-
-
`RouterModule` also offers a `forChild` static method for configuring the routes of lazy-loaded modules.
_forRoot_ and _forChild_ are conventional names for methods that
@@ -318,29 +246,24 @@ configure services in root and feature modules respectively.
Angular doesn't recognize these names but Angular developers do.
Follow this convention when you write similar modules with configurable service providers.
-
-
-
{@a q-module-provider-visibility}
-
-
## Why is a service provided in a feature module visible everywhere?
Providers listed in the `@NgModule.providers` of a bootstrapped module have *application scope*.
Adding a service provider to `@NgModule.providers` effectively publishes the service to the entire application.
-When you import a module,
+When you import an NgModule,
Angular adds the module's service providers (the contents of its `providers` list)
to the application _root injector_.
This makes the provider visible to every class in the application that knows the provider's lookup token.
This is by design.
-Extensibility through module imports is a primary goal of the NgModule system.
-Merging module providers into the application injector
+Extensibility through NgModule imports is a primary goal of the NgModule system.
+Merging NgModule providers into the application injector
makes it easy for a module library to enrich the entire application with new services.
By adding the `HttpModule` once, every application component can make http requests.
@@ -350,42 +273,32 @@ If the `HeroModule` provides the `HeroService` and the root `AppModule` imports
any class that knows the `HeroService` _type_ can inject that service,
not just the classes declared in the `HeroModule`.
-
-
-
{@a q-lazy-loaded-module-provider-visibility}
+## Why is a service provided in a _lazy-loaded_ NgModule visible only to that module?
-
-## Why is a service provided in a _lazy-loaded_ module visible only to that module?
-
-Unlike providers of the modules loaded at launch,
+Unlike providers of the NgModules loaded at launch,
providers of lazy-loaded modules are *module-scoped*.
When the Angular router lazy-loads a module, it creates a new execution context.
That [context has its own injector](guide/ngmodule-faq#q-why-child-injector "Why Angular creates a child injector"),
which is a direct child of the application injector.
-The router adds the lazy module's providers and the providers of its imported modules to this child injector.
+The router adds the lazy module's providers and the providers of its imported NgModules to this child injector.
These providers are insulated from changes to application providers with the same lookup token.
When the router creates a component within the lazy-loaded context,
Angular prefers service instances created from these providers to the service instances of the application root injector.
-
-
-
{@a q-module-provider-duplicates}
+## What if two NgModules provide the same service?
-
-## What if two modules provide the same service?
-
-When two imported modules, loaded at the same time, list a provider with the same token,
+When two imported NgModules, loaded at the same time, list a provider with the same token,
the second module's provider "wins". That's because both providers are added to the same injector.
When Angular looks to inject a service for that token,
@@ -394,45 +307,34 @@ it creates and delivers the instance created by the second provider.
_Every_ class that injects this service gets the instance created by the second provider.
Even classes declared within the first module get the instance created by the second provider.
-If Module A provides a service for token 'X' and imports a module B
-that also provides a service for token 'X', then Module A's service definition "wins".
+If NgModule A provides a service for token 'X' and imports an NgModule B
+that also provides a service for token 'X', then NgModule A's service definition "wins".
-The service provided by the root `AppModule` takes precedence over services provided by imported modules.
+The service provided by the root `AppModule` takes precedence over services provided by imported NgModules.
The `AppModule` always wins.
-
-
-
{@a q-component-scoped-providers}
+## How do I restrict service scope to an NgModule?
-
-## How do I restrict service scope to a module?
-
-When a module is loaded at application launch,
+When an NgModule is loaded at application launch,
its `@NgModule.providers` have *application-wide scope*;
that is, they are available for injection throughout the application.
-Imported providers are easily replaced by providers from another imported module.
+Imported providers are easily replaced by providers from another imported NgModule.
Such replacement might be by design. It could be unintentional and have adverse consequences.
-
-
-
-As a general rule, import modules with providers _exactly once_, preferably in the application's _root module_.
+As a general rule, import NgModules with providers _exactly once_, preferably in the application's _root module_.
That's also usually the best place to configure, wrap, and override them.
-
-
-
-Suppose a module requires a customized `HttpBackend` that adds a special header for all Http requests.
-If another module elsewhere in the application also customizes `HttpBackend`
+Suppose an NgModule requires a customized `HttpBackend` that adds a special header for all Http requests.
+If another NgModule elsewhere in the application also customizes `HttpBackend`
or merely imports the `HttpModule`, it could override this module's `HttpBackend` provider,
losing the special header. The server will reject http requests from this module.
@@ -457,7 +359,7 @@ with the component's own providers.
When a child of this component asks for the `HttpBackend` service,
Angular provides the local `HttpBackend` service,
not the version provided in the application root injector.
-Child components make proper http requests no matter what other modules do to `HttpBackend`.
+Child components make proper HTTP requests no matter what other NgModules do to `HttpBackend`.
Be sure to create module components as children of this module's top component.
@@ -465,15 +367,10 @@ You can embed the child components in the top component's template.
Alternatively, make the top component a routing host by giving it a `
`.
Define child routes and let the router load module components into that outlet.
-
-
-
{@a q-root-component-or-module}
-
-
## Should I add application-wide providers to the root _AppModule_ or the root _AppComponent_?
Register application-wide providers in the root `AppModule`, not in the `AppComponent`.
@@ -484,11 +381,11 @@ they can't inject `AppComponent` services.
Register a service in `AppComponent` providers _only_ if the service must be hidden
from components outside the `AppComponent` tree. This is a rare use case.
-More generally, [prefer registering providers in modules](guide/ngmodule-faq#q-component-or-module) to registering in components.
+More generally, [prefer registering providers in NgModules](guide/ngmodule-faq#q-component-or-module) to registering in components.
Discussion
-Angular registers all startup module providers with the application root injector.
+Angular registers all startup NgModule providers with the application root injector.
The services created from root injector providers are available to the entire application.
They are _application-scoped_.
@@ -504,22 +401,16 @@ But for routed applications, "almost" isn't good enough.
`AppComponent` services don't exist at the root level where routing operates.
Lazy-loaded modules can't reach them.
-In the NgModule page sample applications, if you had registered `UserService` in the `AppComponent`,
+In the [_NgModules_ sample application](guide/ngmodule), if you had registered `UserService` in the `AppComponent`,
the `HeroComponent` couldn't inject it.
The application would fail the moment a user navigated to "Heroes".
-
-
-
-
{@a q-component-or-module}
+## Should I add other providers to an NgModule or a component?
-
-## Should I add other providers to a module or a component?
-
-In general, prefer registering feature-specific providers in modules (`@NgModule.providers`)
+In general, prefer registering feature-specific providers in NgModules (`@NgModule.providers`)
to registering in components (`@Component.providers`).
Register a provider with a component when you _must_ limit the scope of a service instance
@@ -534,32 +425,27 @@ The changes that editor makes to heroes in its service don't touch the hero inst
[Always register _application-wide_ services with the root `AppModule`](guide/ngmodule-faq#q-root-component-or-module),
not the root `AppComponent`.
-
-
-
{@a q-why-bad}
-
-
-## Why is it bad if _SharedModule_ provides a service to a lazy-loaded module?
+## Why is it bad if _SharedModule_ provides a service to a lazy-loaded NgModule?
This question is addressed in the [Why UserService isn't shared](guide/ngmodule#no-shared-module-providers)
-section of the [NgModules](guide/ngmodule) page,
+section of the [NgModules](guide/ngmodule) guide,
which discusses the importance of keeping providers out of the `SharedModule`.
-Suppose the `UserService` was listed in the module's `providers` (which it isn't).
-Suppose every module imports this `SharedModule` (which they all do).
+Suppose the `UserService` was listed in the NgModule's `providers` (which it isn't).
+Suppose every NgModule imports this `SharedModule` (which they all do).
When the app starts, Angular eagerly loads the `AppModule` and the `ContactModule`.
Both instances of the imported `SharedModule` would provide the `UserService`.
-Angular registers one of them in the root app injector (see [What if I import the same module twice?](guide/ngmodule-faq#q-reimport)).
+Angular registers one of them in the root app injector (see [What if I import the same NgModule twice?](guide/ngmodule-faq#q-reimport)).
Then some component injects `UserService`, Angular finds it in the app root injector,
and delivers the app-wide singleton `UserService`. No problem.
-Now consider the `HeroModule` _which is lazy loaded_.
+Now consider the `HeroModule` _which is lazy-loaded_.
When the router lazy loads the `HeroModule`, it creates a child injector and registers the `UserService`
provider with that child injector. The child injector is _not_ the root injector.
@@ -574,62 +460,47 @@ That's almost certainly a mistake.
-
-
To demonstrate, run the live example.
Modify the `SharedModule` so that it provides the `UserService` rather than the `CoreModule`.
Then toggle between the "Contact" and "Heroes" links a few times.
-The username goes bonkers as the Angular creates a new `UserService` instance each time.
-
-
+The username flashes irregularly as the Angular creates a new `UserService` instance each time.
-
-
-
-
{@a q-why-child-injector}
-
-
## Why does lazy loading create a child injector?
-Angular adds `@NgModule.providers` to the application root injector, unless the module is lazy loaded.
-For a lazy-loaded module, Angular creates a _child injector_ and adds the module's providers to the child injector.
+Angular adds `@NgModule.providers` to the application root injector, unless the NgModule is lazy-loaded.
+For a lazy-loaded NgModule, Angular creates a _child injector_ and adds the module's providers to the child injector.
-This means that a module behaves differently depending on whether it's loaded during application start
-or lazy loaded later. Neglecting that difference can lead to [adverse consequences](guide/ngmodule-faq#q-why-bad).
+This means that an NgModule behaves differently depending on whether it's loaded during application start
+or lazy-loaded later. Neglecting that difference can lead to [adverse consequences](guide/ngmodule-faq#q-why-bad).
-Why doesn't Angular add lazy-loaded providers to the app root injector as it does for eagerly loaded modules?
+Why doesn't Angular add lazy-loaded providers to the app root injector as it does for eagerly loaded NgModules?
The answer is grounded in a fundamental characteristic of the Angular dependency-injection system.
An injector can add providers _until it's first used_.
Once an injector starts creating and delivering services, its provider list is frozen; no new providers are allowed.
-When an applications starts, Angular first configures the root injector with the providers of all eagerly loaded modules
+When an applications starts, Angular first configures the root injector with the providers of all eagerly loaded NgModules
_before_ creating its first component and injecting any of the provided services.
Once the application begins, the app root injector is closed to new providers.
-Time passes and application logic triggers lazy loading of a module.
+Time passes and application logic triggers lazy loading of an NgModule.
Angular must add the lazy-loaded module's providers to an injector somewhere.
It can't add them to the app root injector because that injector is closed to new providers.
So Angular creates a new child injector for the lazy-loaded module context.
-
-
-
{@a q-is-it-loaded}
+## How can I tell if an NgModule or service was previously loaded?
-
-## How can I tell if a module or service was previously loaded?
-
-Some modules and their services should be loaded only once by the root `AppModule`.
+Some NgModules and their services should be loaded only once by the root `AppModule`.
Importing the module a second time by lazy loading a module could [produce errant behavior](guide/ngmodule-faq#q-why-bad)
that may be difficult to detect and diagnose.
@@ -638,22 +509,15 @@ from the root app injector. If the injection succeeds, the class has been loaded
You can throw an error or take other remedial action.
Certain NgModules (such as `BrowserModule`) implement such a guard,
-such as this `CoreModule` constructor from the NgModules page.
+such as this `CoreModule` constructor.
-
-
-
-
-
{@a q-entry-component-defined}
-
-
## What is an _entry component_?
An entry component is any component that Angular loads _imperatively_ by type.
@@ -673,7 +537,7 @@ 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.
+or bootstrapped imperatively with the NgModule's `ngDoBootstrap` method.
Components in route definitions are also _entry components_.
A route definition refers to a component by its _type_.
@@ -683,22 +547,17 @@ 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`:
+Angular automatically adds the following types of components to the NgModule'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.
-
-
-
{@a q-bootstrap_vs_entry_component}
-
-
## What's the difference between a _bootstrap_ component and an _entry component_?
A bootstrapped component _is_ an [entry component](guide/ngmodule-faq#q-entry-component-defined)
@@ -711,15 +570,10 @@ it should generate code to bootstrap the application with this component.
There's no need to list a component in both the `bootstrap` and `entryComponent` lists,
although doing so is harmless.
-
-
-
{@a q-when-entry-components}
-
-
## When do I add components to _entryComponents_?
Most application developers won't need to add components to the `entryComponents`.
@@ -737,15 +591,10 @@ it's best to add only the components that are truly _entry components_.
Don't include components that [are referenced](guide/ngmodule-faq#q-template-reference)
in the templates of other components.
-
-
-
{@a q-why-entry-components}
-
-
## Why does Angular need _entryComponents_?
_Entry components_ are also declared.
Why doesn't the Angular compiler generate code for every component in `@NgModule.declarations`?
@@ -772,50 +621,33 @@ and every component reachable from an entry component.
If a component isn't an _entry component_ or wasn't found in a template,
the compiler omits it.
-
-
-
-
{@a q-module-recommendations}
-
-
-## What kinds of modules should I have and how should I use them?
+## What kinds of NgModules should I have and how should I use them?
Every app is different. Developers have various levels of experience and comfort with the available choices.
-Some suggestions and guidelines appear to have wide appeal.
-
-
-
-
-
-
-The following is preliminary guidance based on early experience using NgModules in a few applications.
-Read with appropriate caution and reflection.
-
-
-
-
-
+The following suggestions and guidelines have wide appeal.
### _SharedModule_
+
Create a `SharedModule` with the components, directives, and pipes that you use
-everywhere in your app. This module should consist entirely of `declarations`,
+everywhere in your app. This NgModule should consist entirely of `declarations`,
most of them exported.
The `SharedModule` may re-export other [widget modules](guide/ngmodule-faq#widget-feature-module), such as `CommonModule`,
-`FormsModule`, and modules with the UI controls that you use most widely.
+`FormsModule`, and NgModules with the UI controls that you use most widely.
The `SharedModule` should *not* have `providers` for reasons [explained previously](guide/ngmodule-faq#q-why-bad).
-Nor should any of its imported or re-exported modules have `providers`.
+Nor should any of its imported or re-exported NgModules have `providers`.
If you deviate from this guideline, know what you're doing and why.
Import the `SharedModule` in your _feature_ modules,
both those loaded when the app starts and those you lazy load later.
### _CoreModule_
+
Create a `CoreModule` with `providers` for the singleton services you load when the application starts.
Import `CoreModule` in the root `AppModule` only.
@@ -823,21 +655,16 @@ Never import `CoreModule` in any other module.
Consider making `CoreModule` a [pure services module](guide/ngmodule-faq#service-feature-module) with no `declarations`.
-
-
-
This page sample departs from that advice by declaring and exporting two components that are
only used within the root `AppComponent` declared by `AppModule`.
Someone following this guideline strictly would have declared these components in the `AppModule` instead.
-
-
-
### Feature Modules
+
Create feature modules around specific application business domains, user workflows, and utility collections.
Feature modules tend to fall into one of the following groups:
@@ -851,19 +678,13 @@ Feature modules tend to fall into one of the following groups:
-
-
-Real-world modules are often hybrids that purposefully deviate from the following guidelines.
+Real-world NgModules are often hybrids that purposefully deviate from the following guidelines.
These guidelines are not laws;
follow them unless you have a good reason to do otherwise.
-
-
-
-
@@ -884,7 +705,6 @@ follow them unless you have a good reason to do otherwise.
|
-
Domain feature modules deliver a user experience *dedicated to a particular application domain*
like editing a customer or placing an order.
@@ -907,10 +727,8 @@ follow them unless you have a good reason to do otherwise.
-
-
- For an example, see the [Make _Contact_ a feature module](guide/ngmodule#contact-module-v1)
- section of the [NgModules](guide/ngmodule) page, before routing is introduced.
+ For an example, see the [Feature Modules](guide/ngmodule#contact-module-v1)
+ section of the [NgModules](guide/ngmodule) guide, before routing is introduced.
@@ -938,20 +756,20 @@ follow them unless you have a good reason to do otherwise.
Routed feature modules _shouldn't export anything_.
They don't have to because their components never appear in the template of an external component.
- A lazy-loaded routed feature module should _not be imported_ by any module.
+ A lazy-loaded routed feature module should _not be imported_ by any NgModule.
Doing so would trigger an eager load, defeating the purpose of lazy loading.
- `HeroModule` and `CrisisModule` are lazy loaded. They aren't mentioned among the `AppModule` imports.
+ `HeroModule` and `CrisisModule` are lazy-loaded. They aren't mentioned among the `AppModule` imports.
- But an eager loaded routed feature module must be imported by another module
+ But an eagerly loaded, routed feature module must be imported by another NgModule
so that the compiler learns about its components.
`ContactModule` is eager loaded and therefore listed among the `AppModule` imports.
Routed Feature Modules rarely have _providers_ for reasons [explained earlier](guide/ngmodule-faq#q-why-bad).
When they do, the lifetime of the provided services
- should be the same as the lifetime of the module.
+ should be the same as the lifetime of the NgModule.
Don't provide application-wide singleton services in a routed feature module
- or in a module that the routed module imports.
+ or in an NgModule that the routed module imports.
|
@@ -965,7 +783,7 @@ follow them unless you have a good reason to do otherwise.
- A [routing module](guide/router#routing-module) *provides routing configuration* for another module.
+ A [routing module](guide/router#routing-module) *provides routing configuration* for another NgModule.
A routing module separates routing concerns from its companion module.
@@ -1042,7 +860,7 @@ follow them unless you have a good reason to do otherwise.
|
- A widget module makes *components, directives, and pipes* available to external modules.
+ A widget module makes *components, directives, and pipes* available to external NgModules.
`CommonModule` and `SharedModule` are widget modules.
Many third-party UI component libraries are widget modules.
@@ -1068,7 +886,7 @@ The following table summarizes the key characteristics of each _feature module_
-Real-world modules are often hybrids that knowingly deviate from these guidelines.
+Real-world NgModules are often hybrids that knowingly deviate from these guidelines.
@@ -1246,17 +1064,11 @@ Real-world modules are often hybrids that knowingly deviate from these guideline
|
-
-
-
-
{@a q-ng-vs-js-modules}
-
-
-## What's the difference between Angular and JavaScript Modules?
+## What's the difference between Angular NgModules and JavaScript Modules?
Angular and JavaScript are different yet complementary module systems.
@@ -1264,41 +1076,33 @@ In modern JavaScript, every file is a _module_
(see the [Modules](http://exploringjs.com/es6/ch_modules.html) page of the Exploring ES6 website).
Within each file you write an `export` statement to make parts of the module public:
-
export class AppComponent { ... }
-
-
-
Then you `import` a part in another module:
-
import { AppComponent } from './app.component';
-
-
-
This kind of modularity is a feature of the _JavaScript language_.
An _NgModule_ is a feature of _Angular_ itself.
-Angular's `NgModule` also has `imports` and `exports` and they serve a similar purpose.
+Angular's `@NgModule` metadata also have `imports` and `exports` and they serve a similar purpose.
You _import_ other NgModules so you can use their exported classes in component templates.
-You _export_ this NgModule's classes so they can be imported and used by components of _other_ modules.
+You _export_ this NgModule's classes so they can be imported and used by components of _other_ NgModules.
The NgModule classes differ from JavaScript module class in the following key ways:
* An NgModule bounds [declarable classes](guide/ngmodule-faq#q-declarable) only.
Declarables are the only classes that matter to the [Angular compiler](guide/ngmodule-faq#q-angular-compiler).
* Instead of defining all member classes in one giant file (as in a JavaScript module),
- you list the module's classes in the `@NgModule.declarations` list.
+ you list the NgModule's classes in the `@NgModule.declarations` list.
* An NgModule can only export the [declarable classes](guide/ngmodule-faq#q-declarable)
-it owns or imports from other modules.
+it owns or imports from other NgModules.
It doesn't declare or export any other kind of class.
The NgModule is also special in another way.
@@ -1309,40 +1113,25 @@ by adding providers to the `@NgModule.providers` list.
-
-
-The provided services don't belong to the module nor are they scoped to the declared classes.
+The provided services don't belong to the NgModule nor are they scoped to the declared classes.
They are available _everywhere_.
-
+Here's an _@NgModule_ class with imports, exports, and declarations.
-
-Here's an _NgModule_ class with imports, exports, and declarations.
-
-
-
+
-
-
Of course you use _JavaScript_ modules to write NgModules as seen in the complete `contact.module.ts` file:
-
-
-
-
-
{@a q-template-reference}
-
-
## How does Angular find components, directives, and pipes in a template?
What is a template reference?
The [Angular compiler](guide/ngmodule-faq#q-angular-compiler) looks inside component templates
@@ -1353,18 +1142,13 @@ component or directive to some HTML in that template.
The compiler finds a pipe if the pipe's *name* appears within the pipe syntax of the template HTML.
-Angular only matches selectors and pipe names for classes that are declared by this module
-or exported by a module that this module imports.
-
+Angular only matches selectors and pipe names for classes that are declared by this NgModule
+or exported by an NgModule that this one imports.
-
-
{@a q-angular-compiler}
-
-
## What is the Angular compiler?
The Angular compiler converts the application code you write into highly performant JavaScript code.
@@ -1386,20 +1170,15 @@ Because *directives* and *pipes* appear in component templates,
the Angular compiler incorporates them into compiled component code too.
`@NgModule` metadata tells the Angular compiler what components to compile for this module and
-how to link this module with other modules.
-
+how to link this module with other NgModules.
-
-
{@a q-ngmodule-api}
+## @NgModule API
-
-## NgModule API
-
-The following table summarizes the `NgModule` metadata properties.
+The following table summarizes the `@NgModule` metadata properties.
@@ -1425,16 +1204,16 @@ The following table summarizes the `NgModule` metadata properties.
A list of [declarable](guide/ngmodule-faq#q-declarable) classes,
- the *component*, *directive*, and *pipe* classes that _belong to this module_.
+ the *component*, *directive*, and *pipe* classes that _belong to this NgModule_.
- These declared classes are visible within the module but invisible to
- components in a different module unless they are _exported_ from this module and
- the other module _imports_ this one.
+ These declared classes are visible within the NgModule but invisible to
+ components in a different NgModule unless they are _exported_ from this NgModule and
+ the other NgModule _imports_ this one.
- Components, directives, and pipes must belong to _exactly_ one module.
- The compiler emits an error if you try to declare the same class in more than one module.
+ Components, directives, and pipes must belong to _exactly_ one NgModule.
+ The compiler emits an error if you try to declare the same class in more than one NgModule.
- *Do not re-declare a class imported from another module.*
+ *Do not re-declare a class imported from another NgModule.*
@@ -1451,22 +1230,22 @@ The following table summarizes the `NgModule` metadata properties.
A list of dependency-injection providers.
- Angular registers these providers with the root injector of the module's execution context.
- That's the application's root injector for all modules loaded when the application starts.
+ Angular registers these providers with the root injector of the NgModule's execution context.
+ That's the application's root injector for all NgModules loaded when the application starts.
Angular can inject one of these provider services into any component in the application.
- If this module or any module loaded at launch provides the `HeroService`,
+ If this NgModule or any NgModule loaded at launch provides the `HeroService`,
Angular can inject the same `HeroService` intance into any app component.
- A lazy-loaded module has its own sub-root injector which typically
+ A lazy-loaded NgModule has its own sub-root injector which typically
is a direct child of the application root injector.
Lazy-loaded services are scoped to the lazy module's injector.
- If a lazy-loaded module also provides the `HeroService`,
+ If a lazy-loaded NgModule also provides the `HeroService`,
any component created within that module's context (such as by router navigation)
gets the local instance of the service, not the instance in the root application injector.
- Components in external modules continue to receive the instance created for the application root.
+ Components in external NgModules continue to receive the instance created for the application root.
@@ -1481,20 +1260,20 @@ The following table summarizes the `NgModule` metadata properties.
- A list of supporting modules.
+ A list of supporting NgModules.
- Specifically, the list of modules whose exported components, directives, or pipes
- are referenced by the component templates declared in this module.
+ Specifically, the list of NgModules whose exported components, directives, or pipes
+ are referenced by the component templates declared in this NgModule.
A component template can [reference](guide/ngmodule-faq#q-template-reference) another component, directive, or pipe
when the referenced class is declared in this module
or the class was imported from another module.
- A component can use the `NgIf` and `NgFor` directives only because its parent module
+ A component can use the `NgIf` and `NgFor` directives only because its declaring NgModule
imported the Angular `CommonModule` (perhaps indirectly by importing `BrowserModule`).
You can import many standard directives with the `CommonModule`
- but some familiar directives belong to other modules.
+ but some familiar directives belong to other NgModules.
A component template can bind with `[(ngModel)]` only after importing the Angular `FormsModule`.
|
@@ -1510,25 +1289,25 @@ The following table summarizes the `NgModule` metadata properties.
A list of declarations—*component*, *directive*, and *pipe* classes—that
- an importing module can use.
+ an importing NgModule can use.
Exported declarations are the module's _public API_.
- A component in another module can [reference](guide/ngmodule-faq#q-template-reference) _this_ module's `HeroComponent`
+ A component in another NgModule can [reference](guide/ngmodule-faq#q-template-reference) _this_ NgModule's `HeroComponent`
if it imports this module and this module exports `HeroComponent`.
Declarations are private by default.
- If this module does _not_ export `HeroComponent`, no other module can see it.
+ If this NgModule does _not_ export `HeroComponent`, no other NgModule can see it.
- Importing a module does _not_ automatically re-export the imported module's imports.
- Module 'B' can't use `ngIf` just because it imported module `A` which imported `CommonModule`.
- Module 'B' must import `CommonModule` itself.
+ Importing an NgModule does _not_ automatically re-export the imported NgModule's imports.
+ NgModule 'B' can't use `ngIf` just because it imported NgModule `A` which imported `CommonModule`.
+ NgModule 'B' must import `CommonModule` itself.
- A module can list another module among its `exports`, in which case
- all of that module's public components, directives, and pipes are exported.
+ An NgModule can list another NgModule among its `exports`, in which case
+ all of that NgModule's public components, directives, and pipes are exported.
- [Re-export](guide/ngmodule-faq#q-re-export) makes module transitivity explicit.
- If Module 'A' re-exports `CommonModule` and Module 'B' imports Module 'A',
- Module 'B' components can use `ngIf` even though 'B' itself didn't import `CommonModule`.
+ [Re-export](guide/ngmodule-faq#q-re-export) makes NgModule transitivity explicit.
+ If NgModule 'A' re-exports `CommonModule` and NgModule 'B' imports NgModule 'A',
+ NgModule 'B' components can use `ngIf` even though 'B' itself didn't import `CommonModule`.
@@ -1598,4 +1377,3 @@ The following table summarizes the `NgModule` metadata properties.
-
diff --git a/aio/content/guide/ngmodule.md b/aio/content/guide/ngmodule.md
index 4d6b9addcf..5d00bdbb4c 100644
--- a/aio/content/guide/ngmodule.md
+++ b/aio/content/guide/ngmodule.md
@@ -4,44 +4,26 @@
-An NgModule is a class adorned with the *@NgModule* decorator function.
-`@NgModule` takes a metadata object that tells Angular how to compile and run module code.
+An NgModule is a class adorned with the **@NgModule** decorator function.
+`@NgModule` takes a metadata object that tells Angular how to compile and your code.
It identifies the module's own components, directives, and pipes,
making some of them public so external components can use them.
`@NgModule` may add service providers to the application dependency injectors.
And there are many more options covered here.
-Before reading this page, read the
-[The Root Module](guide/bootstrapping) page, which introduces NgModules and the essentials
+{@a bootstrap}
+
+For a quick overview of NgModules, consider reading the
+[Bootstrapping](guide/bootstrapping) guide, which introduces NgModules and the essentials
of creating and maintaining a single root `AppModule` for the entire application.
-This page covers NgModules in greater depth.
-
-
+_This_ page covers NgModules in greater depth.
#### Live examples
-This page explains NgModules through a progression of improvements to a sample with a "Tour of Heroes" theme.
+This page explains NgModules through a progression of improvements to a sample with a "Heroes" theme.
Here's an index to live examples at key moments in the evolution of the sample:
-* A minimal NgModule app
+* The initial app
* The first contact module
* The revised contact module
* Just before adding SharedModule
@@ -55,20 +37,15 @@ The companion [NgModule FAQs](guide/ngmodule-faq "NgModule FAQs") guide
offers answers to specific design and implementation questions.
Read this page before reading those FAQs.
-
-
-
{@a angular-modularity}
-
-
## Angular modularity
-Modules are a great way to organize an application and extend it with capabilities from external libraries.
+NgModules are a great way to organize an application and extend it with capabilities from external libraries.
-Many Angular libraries are modules (such as `FormsModule`, `HttpModule`, and `RouterModule`).
+Many Angular libraries are NgModules (such as `FormsModule`, `HttpModule`, and `RouterModule`).
Many third-party libraries are available as NgModules (such as
Material Design,
Ionic,
@@ -78,355 +55,338 @@ NgModules consolidate components, directives, and pipes into
cohesive blocks of functionality, each focused on a
feature area, application business domain, workflow, or common collection of utilities.
-Modules can also add services to the application.
+NgModules can also add services to the application.
Such services might be internally developed, such as the application logger.
Services can come from outside sources, such as the Angular router and Http client.
-Modules can be loaded eagerly when the application starts.
-They can also be _lazy loaded_ asynchronously by the router.
+NgModules can be loaded eagerly when the application starts.
+They can also be _lazy-loaded_ asynchronously by the router.
-An NgModule is a class decorated with `@NgModule` metadata. The metadata do the following:
-
-* Declare which components, directives, and pipes belong to the module.
-* Make some of those classes public so that other component templates can use them.
-* Import other modules with the components, directives, and pipes needed by the components in _this_ module.
-* Provide services at the application level that any application component can use.
-
-Every Angular app has at least one module class, the _root module_.
-You bootstrap that module to launch the application.
-
-The root module is all you need in a simple application with a few components.
-As the app grows, you refactor the root module into *feature modules*
-that represent collections of related functionality.
-You then import these modules into the root module.
-
-Later in this page, you'll read about this process. For now, you'll start with the root module.
+An NgModule is a class decorated with `@NgModule` metadata.
+By setting metadata properties you tell Angular how your application parts fit together.
+For example, you can do the following:
+* _Declare_ which components, directives, and pipes belong to the NgModule.
+* _Export_ some of those classes so that other component templates can use them.
+* _Import_ other NgModules with the components, directives, and pipes needed by the components in _this_ NgModule.
+* _Provide_ services at the application level that any application component can use.
+* _Bootstrap_ the app with one or more top-level, _root_ components.
{@a root-module}
-
-
## The root _AppModule_
-Every Angular app has a *root module* class.
+Every Angular app has at least one NgModule class, the _root module_.
+You bootstrap _that_ NgModule to launch the application.
+
By convention, the *root module* class is called `AppModule` and it exists in a file named `app.module.ts`.
+The [**Angular CLI**](https://cli.angular.io/) generates the initial `AppModule` for you when you create a project.
-The `AppModule` from the QuickStart seed on the [Setup](guide/setup) page is as minimal as possible:
-
-
-
+
+ng new quickstart
+The root `AppModule` is all you need in a simple application with a few components.
+As the app grows, you may refactor the root `AppModule` into [*feature modules*](#feature-modules)
+that represent collections of related functionality.
+For now, stick with the root `AppModule` created by the CLI.
-The `@NgModule` decorator defines the metadata for the module.
-This page takes an intuitive approach to understanding the metadata and fills in details as it progresses.
+
+
-The metadata imports a single helper module, `BrowserModule`, which every browser app must import.
+The initial `declarations` array identifies the application's only component, `AppComponent`,
+the _root component_ at the top of the app's component tree.
+Soon you'll declare more [components](#declare-component)
+(and [directives](#declare-directive) and [pipes](#declare-pipe) too).
+
+The `@NgModule` metadata `imports` a single helper module, `BrowserModule`, which every browser app must import.
`BrowserModule` registers critical application service providers.
It also includes common directives like `NgIf` and `NgFor`, which become immediately visible and usable
-in any of this module's component templates.
+in any of this NgModule's component templates.
-The `declarations` list identifies the application's only component,
-the _root component_, the top of the app's rather bare component tree.
+The `providers` array registers services with the top-level [_dependency injector_](guide/dependency-injection).
+There are no services to register ... yet.
-The example `AppComponent` simply displays a data-bound title:
+Lastly, the `bootstrap` list identifies the `AppComponent` as the _bootstrap component_.
+When Angular launches the app, it renders the `AppComponent`
+inside the `` element tag of the `index.html`.
-
+Learn about that in the [bootstrapping](guide/bootstrapping) guide.
+
+
+The CLI-generated `AppComponent` in this guide's sample has been simplified and consolidated into a single `app.component.ts` file like this:
+
+
+
+Run the app and follow along with the steps in this guide:
-Lastly, the `@NgModule.bootstrap` property identifies this `AppComponent` as the _bootstrap component_.
-When Angular launches the app, it places the HTML rendering of `AppComponent` in the DOM,
-inside the `` element tags of the `index.html`.
-
-
-{@a bootstrap}
-
-
-
-## Bootstrapping in _main.ts_
-You launch the application by bootstrapping the `AppModule` in the `main.ts` file.
-
-Angular offers a variety of bootstrapping options targeting multiple platforms.
-This page describes two options, both targeting the browser.
-
-### Compile just-in-time (JIT)
-In the first, _dynamic_ option, the [Angular compiler](guide/ngmodule-faq#q-angular-compiler "About the Angular Compiler")
-compiles the application in the browser and then launches the app.
-
-
-
-
+
+ng serve
-
-
-The samples in this page demonstrate the dynamic bootstrapping approach.
-
-Try the live example.
-
-
-### Compile ahead-of-time (AOT)
-
-Consider the static alternative which can produce a much smaller application that
-launches faster, especially on mobile devices and high latency networks.
-
-In the _static_ option, the Angular compiler runs ahead of time as part of the build process,
-producing a collection of class factories in their own files.
-Among them is the `AppModuleNgFactory`.
-
-The syntax for bootstrapping the pre-compiled `AppModuleNgFactory` is similar to
-the dynamic version that bootstraps the `AppModule` class.
-
-
-
-
-
-
-
-
-Because the entire application was pre-compiled,
-Angular doesn't ship the Angular compiler to the browser and doesn't compile in the browser.
-
-The application code downloaded to the browser is much smaller than the dynamic equivalent
-and it's ready to execute immediately. The performance boost can be significant.
-
-Both the JIT and AOT compilers generate an `AppModuleNgFactory` class from the same `AppModule`
- source code.
-The JIT compiler creates that factory class on the fly, in memory, in the browser.
-The AOT compiler outputs the factory to a physical file
-that is imported here in the static version of `main.ts`.
-
-In general, the `AppModule` should neither know nor care how it is bootstrapped.
-
-Although the `AppModule` evolves as the app grows, the bootstrap code in `main.ts` doesn't change.
-This is the last time you'll look at `main.ts`.
-
-
-
-
{@a declarations}
+{@a declare-directive}
+## Declare directives
+{@a declarables}
-## Declare directives and components
-As the app evolves,
-the first addition is a `HighlightDirective`, an [attribute directive](guide/attribute-directives)
-that sets the background color of the attached element.
+As the app evolves, you'll add directives, components, and pipes (the _declarables_).
+You must declare each of these classes in an NgModule.
+
+As an exercise, begin by adding a `highlight.directive.ts` to the `src/app/` folder _by hand_.
-
+The `HighlightDirective` is an [attribute directive](guide/attribute-directives)
+that sets the background color of its host element.
+Update the `AppComponent` template to attach this directive to the `` title element:
-
-Update the `AppComponent` template to attach the directive to the title:
-
-
-
+
+The screen of the running app has not changed.
+The `` is not highlighted.
+Angular does not yet recognize the `highlight` attribute and is ignoring it.
+You must declare the `HighlightDirective` in `AppModule`.
+Edit the `app.module.ts` file, import the `HighlightDirective`,
+and add it to the `AppModule` _declarations_ like this:
-If you ran the app now, Angular wouldn't recognize the `highlight` attribute and would ignore it.
-You must declare the directive in `AppModule`.
-
-Import the `HighlightDirective` class and add it to the module's `declarations` like this:
-
-
-
+
-Refactor the title into its own `TitleComponent`.
-The component's template binds to the component's `title` and `subtitle` properties like this:
+The Angular CLI would have done all of this for you
+if you'd created the `HighlightDirective` with the CLI command like this:
+
+
+ng generate directive highlight
+
+
+But you didn't.
+You created the file by hand so you must declare the directive by hand.
+
+{@a declare-component}
+
+## Declare components
+
+Now add a `TitleComponent` to the app and this time create it with the CLI.
+
+
+ng generate component title --flat --no-spec --inline-style
+
+
+
+
+The `--flat` flag tells the CLI to generate all files to the `src/app/` folder.
+The `--no-spec` flag skips the test (`.spec`) file.
+The `--inline-style` flag prevents generation of the `.css` file (which you won't need).
+
+
+
+
+
+To see which files would be created or changed by any `ng generate` command, append the `--dryRun` flag (`-d` for short).
+
+
+
+Open the `AppModule` and look at the `declarations` where you will see that the CLI added
+the `TitleComponent` for you.
+
+
+
+
+Now rewrite the `title.component.html` like this.
-
-
+And move the `title` property from `app.component.ts` into the `title.component.ts`, which looks as follows after a little cleanup.
-
-
-
-Rewrite the `AppComponent` to display the new `TitleComponent` in the `` element,
-using an input binding to set the `subtitle`.
+Rewrite `AppComponent` to display the new `TitleComponent` in the `` element and get rid of the `title` property.
-
+#### Error if component not declared
+There was no visible clue when you neglected to declare the `HighlightDirective` attribute directive.
+The Angular compiler doesn't recognize `highlight` as an `` attribute but it doesn't complain either.
+You'd discover it was undeclared only if you were looking for its effect.
-Angular won't recognize the `` tag until you declare it in `AppModule`.
-Import the `TitleComponent` class and add it to the module's `declarations`:
+Now try removing the declaration of the `TitleComponent` from `AppModule`.
-
+The Angular compiler behaves differently when it encounters an unrecognized HTML element.
+The app ceases to display the page and
+the browser console logs the following error
+
+Uncaught Error: Template parse errors:
+'app-title' is not a known element:
+1. If 'app-title' is an Angular component, then verify that it is part of this NgModule.
+2. If 'app-title' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
+
+
+
+
+If you don't get that error, you might get this one:
+
+
+Uncaught Error: Component TitleComponent is not part of any NgModule or the module has not been imported into your module.
+
+**Always declare your [components](#declare-component), [directives](#declare-directive), and [pipes](#declare-pipe)**.
{@a providers}
-
-
## Service providers
-Modules are a great way to provide services for all of the module's components.
-
The [Dependency Injection](guide/dependency-injection) page describes
the Angular hierarchical dependency-injection system and how to configure that system
-with [providers](guide/dependency-injection#providers) at different levels of the
-application's component tree.
+with [providers](guide/dependency-injection#providers).
-A module can add providers to the application's root dependency injector, making those services
-available everywhere in the application.
+### NgModule providers
+
+An NgModule can provide services.
+A single instance of each provided service becomes available for injection into every class created with that NgModule's injector (or one of its descendant injectors).
+
+When Angular boots the application,
+it creates the root `AppModule` with a root dependency injector.
+Angular configures the root injector with the providers specified in the module's `@NgModule.providers`.
+
+Later, when Angular creates a new instance of a class— be it a component, directive, service, or module— that new class can be injected with an instance of a service provided to the root injector by the `AppModule`.
+
+
+
+Angular also configures the root injector with the providers specified by [imported NgModules](#imports).
+An NgModule's own providers are registered _after_ imported NgModule providers.
+When there are multiple providers for the same injection token, the last registration wins.
+
+
+
+### Compared to Component providers
+
+Providing a service in `@Component.providers` metadata means that a new service instance will be created for each new instance of _that_ component and will be available for injection into _all of that component instance's descendant sub-components_.
+
+The service instance won't be injected into any other component instances.
+Other instances of the same component class cannot see it.
+Sibling and ancestor component instances cannot see it.
+
+Component providers always supersede NgModule providers.
+A component provider for injection token `X` creates a new service instance that "shadows" an NgModule provider for injection token `X`.
+When the component or any of its sub-components inject `X`, they get the _component_ service instance, not the _NgModule_ service instance.
+
+Should you provide a service in an _NgModule_ or a _component_?
+The answer depends on how you want to scope the service.
+If the service should be widely available, provide it in an NgModule.
+If it should be visible only within a component tree, provide it in the component at the root of that tree.
+
+### NgModule provider example
Many applications capture information about the currently logged-in user and make that information
accessible through a user service.
-This sample application has a dummy implementation of such a `UserService`.
+Use the CLI to create a `UserService` and provide it in the root `AppModule`.
+
+
+ng generate service user --module=app
+
+
+This command creates a skeleton `UserService` in `src/app/user.service.ts` and a companion test file, `src/app/user.service.spec.ts`.
+
+The `--module=app` flag tells the CLI to provide the service class in the NgModule defined in the `src/app/app.module.ts` file.
+
+If you omit the `--module` flag, the CLI still creates the service but _does not provide it_ anywhere.
+You have to do that yourself.
+
+Confirm that the `--module=app` flag did provide the service in the root `AppModule` by inspecting the `@NgModule.providers` array in `src/app/app.module.ts`
+
+
+
+
+Replace the generated contents of `src/app/user.service.ts` with the following dummy implementation.
-
-
-
-The sample application should display a welcome message to the logged-in user just below the application title.
-Update the `TitleComponent` template to show the welcome message below the application title.
-
-
-
-
-
-
-
Update the `TitleComponent` class with a constructor that injects the `UserService`
and sets the component's `user` property from the service.
-
+Update the `TitleComponent` template to show the welcome message below the application title.
-
-You've defined and used the service. Now to _provide_ it for all components to use,
-add it to a `providers` property in the `AppModule` metadata:
-
-
-
+
-
-
{@a imports}
-
-
-## Import supporting modules
+## NgModule imports
In the revised `TitleComponent`, an `*ngIf` directive guards the message.
There is no message if there is no user.
-
-
-
-Although `AppModule` doesn't declare `NgIf`, the application still compiles and runs.
+Although `AppModule` doesn't declare the `NgIf` directive, the application still compiles and runs.
How can that be? The Angular compiler should either ignore or complain about unrecognized HTML.
-Angular does recognize `NgIf` because you imported it earlier.
-The initial version of `AppModule` imports `BrowserModule`.
+### Importing _BrowserModule_
+
+Angular does recognize `NgIf` because the `AppModule` imports it indirectly
+when it imports `BrowserModule`.
-
-
Importing `BrowserModule` made all of its public components, directives, and pipes visible
-to the component templates in `AppModule`.
+to the templates of components declared in `AppModule`, which include `TitleComponent`.
-
+{@a reexport}
+### Re-exported NgModules
-
-More accurately, `NgIf` is declared in `CommonModule` from `@angular/common`.
+The `NgIf` directive isn't declared in `BrowserModule`.
+It's declared in `CommonModule` from `@angular/common`.
`CommonModule` contributes many of the common directives that applications need, including `ngIf` and `ngFor`.
-`BrowserModule` imports `CommonModule` and [re-exports](guide/ngmodule-faq#q-re-export) it.
-The net effect is that an importer of `BrowserModule` gets `CommonModule` directives automatically.
-
-
-
+`AppModule` doesn't import `CommonModule` directly.
+But it benefits from the fact that `BrowserModule` imports `CommonModule`
+**and [re-exports](guide/ngmodule-faq#q-re-export) it**.
+The net effect is that an importer of `BrowserModule` gets `CommonModule` directives automatically as if it had declared them itself.
Many familiar Angular directives don't belong to `CommonModule`.
-For example, `NgModel` and `RouterLink` belong to Angular's `FormsModule` and `RouterModule` respectively.
-You must import those modules before you can use their directives.
+For example, `NgModel` and `RouterLink` belong to Angular's `FormsModule` and `RouterModule` respectively.
+You must import those NgModules before you can use their directives.
-To illustrate this point, you'll extend the sample app with `ContactComponent`,
-a form component that imports form support from the Angular `FormsModule`.
+To illustrate this point, you'll extend the sample app with _contact editor_ whose `ContactComponent` is a form component.
+You'll have to import form support from the Angular `FormsModule`.
-Add the _ContactComponent_
+{@a add-contact-editor}
-[Angular forms](guide/forms) are a great way to manage user data entry.
+### Add a _contact editor_
-The `ContactComponent` presents a "contact editor,"
-implemented with Angular forms in the [template-driven form](guide/forms#template-driven) style.
-
-
-
-
-
-
-
Angular form styles
-
-You can write Angular form components in
-template-driven or
-[reactive](guide/dynamic-form) style.
-
-
-The following sample imports the `FormsModule` from `@angular/forms` because
-the `ContactComponent` is written in _template-driven_ style.
-Modules with components written in the _reactive_ style
-import the `ReactiveFormsModule`.
-
-
-
-
-
-
-The `ContactComponent` selector matches an element named ``.
-Add an element with that name to the `AppComponent` template, just below the ``:
-
-
-
-
-
-
-
-Form components are often complex. The `ContactComponent` has its own `ContactService`
-and [custom pipe](guide/pipes#custom-pipes) (called `Awesome`),
-and an alternative version of the `HighlightDirective`.
-
-To make it manageable, place all contact-related material in an `src/app/contact` folder
-and break the component into three constituent HTML, TypeScript, and css files:
+Imagine that you added the following _contact editor_ files
+to the project by hand _without the help of the CLI_.
@@ -450,234 +410,138 @@ and break the component into three constituent HTML, TypeScript, and css files:
-
+
+
+Form components are often complex and this is one is no exception.
+To make it manageable, all contact-related files are in an `src/app/contact` folder.
-In the middle of the component template,
-notice the two-way data binding `[(ngModel)]`.
-`ngModel` is the selector for the `NgModel` directive.
+The `ContactComponent` implementation is spread over three constituent HTML, TypeScript, and css files.
-Although `NgModel` is an Angular directive, the _Angular compiler_ won't recognize it for the following reasons:
+There's a [custom pipe](guide/pipes#custom-pipes) (called `Awesome`),
+a `ContactHighlightDirective`, and a `ContactService` for fetching contacts.
-* `AppModule` doesn't declare `NgModel`.
-* `NgModel` wasn't imported via `BrowserModule`.
-
-Even if Angular somehow recognized `ngModel`,
-`ContactComponent` wouldn't behave like an Angular form because
-form features such as validation aren't yet available.
-
-
Import the FormsModule
-
-Add the `FormsModule` to the `AppModule` metadata's `imports` list.
-
-
+The `ContactService` was added to the `AppModule` providers.
+
+Now any class can inject the application-wide instances of the `ContactService` and `UserService`.
+
+
+### Import supporting _FormsModule_
+
+The `ContactComponent` is written with Angular forms in the [template-driven](guide/forms#template-driven) style.
+
+Notice the `[(ngModel)]` binding in the middle of the component template, `contact.component.html`.
+
+
+
+
+Two-way data binding `[(ngModel)]`is typical of the _template-driven_ style.
+The `ngModel` is the selector for the `NgModel` directive.
+Although `NgModel` is an Angular directive,
+the _Angular compiler_ won't recognize it for two reasons:
+
+1. `AppModule` doesn't declare `NgModel` (and shouldn't).
+2. `NgModel` wasn't imported via `BrowserModule`.
+
+`ContactComponent` wouldn't behave like an Angular form anyway because
+form features such as validation aren't part of the Angular core.
+
+To correct these problems, the `AppModule` must import _both_ the `BrowserModule`
+_and_ the **FormsModule from '@angular/forms'** like this.
+
+
+
+
+
+
+You can write Angular form components in template-driven or [reactive](guide/reactive-forms) style.
+NgModules with components written in the _reactive_ style
+import the `ReactiveFormsModule`.
+
+
Now `[(ngModel)]` binding will work and the user input will be validated by Angular forms,
-once you declare the new component, pipe, and directive.
+once you [declare the new component, pipe, and directive](#declare-pipe).
+### Never re-declare
+
+Importing the `FormsModule` makes the `NgModelDirective` (and all of the other `FORMS_DIRECTIVES`) available to components declared in `AppModule`.
+
+*Do not also* add these directives to the `AppModule` metadata's declarations.
-
-
-*Do not* add `NgModel`—or the `FORMS_DIRECTIVES`—to
-the `AppModule` metadata's declarations.
-These directives belong to the `FormsModule`.
-
-Components, directives, and pipes belong to _one module only_.
-
-*Never re-declare classes that belong to another module.*
-
+**Never re-declare classes that belong to another NgModule.**
+Components, directives, and pipes should be declared in _exactly one NgModule_.
-
-
{@a declare-pipe}
+## Declare pipes
-Declare the contact component, directive, and pipe
+The revised application still won't compile until you declare the contact component, directive, and pipe.
-The application won't compile until you declare the contact component, directive, and pipe.
-Update the `declarations` in the `AppModule` accordingly:
+Components and directives are *declarables*. So are **pipes**.
+
+You [learned earlier](#declarations) to generate and declare both components and directives with the CLI `ng generate` commands.
+
+There's also a CLI command to generate and declare the `AwesomePipe`:
+
+
+ng generate pipe awesome
+
+
+However, if you write these class files by hand or opt-out of declaration with the `--skip-import` flag, you'll have to add the declarations yourself.
+
+[You were told](#add-contact-editor) to add the _contact editor_ files by hand, so
+you must manually update the `declarations` in the `AppModule`:
-
+Display the ContactComponent
+Update the `AppComponent` template to display the `ContactComponent` by placing an
+element with its selector (``) just below the title.
-{@a import-name-conflict}
-
-
-
-
-
-
-There are two directives with the same name, both called `HighlightDirective`.
-
-To work around this, create an alias for the contact version using the `as` JavaScript import keyword.
-
-
-
+
-
-
-This solves the immediate issue of referencing both directive _types_ in the same file but
-leaves another issue unresolved.
-You'll learn more about that issue later in this page, in [Resolve directive conflicts](guide/ngmodule#resolve-conflicts).
-
-
-
-
-
-
-Provide the _ContactService_
-The `ContactComponent` displays contacts retrieved by the `ContactService`,
-which Angular injects into its constructor.
-
-You have to provide that service somewhere.
-The `ContactComponent` could provide it,
-but then the service would be scoped to this component only.
-You want to share this service with other contact-related components that you'll surely add later.
-
-In this app, add `ContactService` to the `AppModule` metadata's `providers` list:
-
-
-
-
-
-
-
-Now you can inject `ContactService` (like `UserService`) into any component in the application.
-
-
-{@a application-scoped-providers}
-
-
-
-
-
-
-
Application-scoped providers
- The `ContactService` provider is _application_-scoped because Angular
- registers a module's `providers` with the application's *root injector*.
-
- Architecturally, the `ContactService` belongs to the Contact business domain.
- Classes in other domains don't need the `ContactService` and shouldn't inject it.
-
- You might expect Angular to offer a _module_-scoping mechanism to enforce this design.
- It doesn't. NgModule instances, unlike components, don't have their own injectors
- so they can't have their own provider scopes.
-
- This omission is intentional.
- NgModules are designed primarily to extend an application,
- to enrich the entire app with the module's capabilities.
-
- In practice, service scoping is rarely an issue.
- Non-contact components can't accidentally inject the `ContactService`.
- To inject `ContactService`, you must first import its _type_.
- Only Contact components should import the `ContactService` type.
-
- Read more in the [How do I restrict service scope to a module?](guide/ngmodule-faq#q-component-scoped-providers) section
- of the [NgModule FAQs](guide/ngmodule-faq) page.
-
-
-
-
-
-
Run the app
Everything is in place to run the application with its contact editor.
-The app file structure looks like this:
-
-
-
-
- app
-
-
-
-
-
- app.component.ts
-
-
-
- app.module.ts
-
-
-
- highlight.directive.ts
-
-
-
- title.component.(html|ts)
-
-
-
- user.service.ts
-
-
-
- contact
-
-
-
-
-
- awesome.pipe.ts
-
-
-
- contact.component.(css|html|ts)
-
-
-
- contact.service.ts
-
-
-
- highlight.directive.ts
-
-
-
-
-
-
-
-
-
-
Try the example:
+## Selector conflicts
-{@a resolve-conflicts}
+Look closely at the screen.
+Notice that the background of the application title text is _blue_.
+It should be _gold_ (see `src/app/app.component.html`).
+Only the contact name should be blue (see `src/app/contact/contact.component.html`).
+What went wrong?
-## Resolve directive conflicts
-
+This application defines two highlight directives that
+set the background color of their host elements with a different color (gold and blue).
-An issue arose [earlier](guide/ngmodule#import-name-conflict) when you declared the contact's `HighlightDirective` because
-you already had a `HighlightDirective` class at the application level.
+One is defined at the root level (`src/app/highlight.directive.ts`);
+the other is in the contact editor folder (`src/app/contact/contact-highlight.directive.ts`).
-The selectors of the two directives both highlight the attached element with a different color.
+Their class names are different (`HighlightDirective` and `ContactHighlightDirective`)
+but their selectors both match any HTML element with a `highlight` attribute.
@@ -685,592 +549,696 @@ The selectors of the two directives both highlight the attached element with a d
-
+
+Both directives are declared in the same `AppModule` so both directives are active
+for all components declared in `AppModule`.
+There's nothing intrinsically wrong with multiple directives selecting the same element.
+Each could modify the element in a different, non-conflicting way.
-Both directives are declared in this module so both directives are active.
+In _this case_, both directives compete to set the background color of the same element.
+The directive that's declared later (`ContactHighlightDirective`) always wins because its DOM changes overwrite the changes by the earlier `HighlightDirective`.
-When the two directives compete to color the same element,
-the directive that's declared later wins because its DOM changes overwrite the first.
-In this case, the contact's `HighlightDirective` makes the application title text blue
-when it should stay gold.
+The `ContactHighlightDirective` will make the application title text blue
+when it should be gold.
+Only the contact name should be blue (see `src/app/contact/contact.component.html`).
+If you cannot rename the selectors, you can resolve the conflicts by creating [feature modules](#feature-modules)
+that insulate the declarations in one NgModule from the declarations in another.
+While it is legal to declare two _directives_ with the same selector in the same NgModule,
+the compiler will not let you declare two _components_ with the same selector in the same NgModule because it **cannot insert multiple components in the same DOM location**.
+Nor can you _import_ an NgModule that declares the same selector as another component in this NgModule.
+The reason is the same: an HTML element may be controlled by at most one Angular component.
-The issue is that two different classes are trying to do the same thing.
-
-It's OK to import the same directive class multiple times.
-Angular removes duplicate classes and only registers one of them.
-
-But from Angular's perspective, two different classes, defined in different files, that have the same name
-are not duplicates. Angular keeps both directives and
-they take turns modifying the same HTML element.
-
+Either rename the selectors or use [feature modules](#feature-modules) to eliminate the conflict.
-
-
-At least the app still compiles.
-If you define two different component classes with the same selector specifying the same element tag,
-the compiler reports an error. It can't insert two components in the same DOM location.
-
-To eliminate component and directive conflicts, create feature modules
-that insulate the declarations in one module from the declarations in another.
-
-
-{@a feature-modules}
-
-
-
## Feature modules
-This application isn't big yet, but it's already experiencing structural issues.
+This tiny app is already experiencing structural issues.
* The root `AppModule` grows larger with each new application class.
+
+
* There are conflicting directives.
-The `HighlightDirective` in the contact re-colors the work done by the `HighlightDirective` declared in `AppModule`.
-Also, it colors the application title text when it should color only the `ContactComponent`.
+The `ContactHighlightDirective` in the contact re-colors the work done by the `HighlightDirective` declared in `AppModule` and colors the application title text when it should color only the `ContactComponent`.
+
+
* The app lacks clear boundaries between contact functionality and other application features.
That lack of clarity makes it harder to assign development responsibilities to different teams.
-You can resolve these issues with _feature modules_.
+_Feature modules_ can help resolve these issues.
-A feature module is a class adorned by the `@NgModule` decorator and its metadata,
-just like a root module.
-Feature module metadata have the same properties as the metadata for a root module.
+Architecturally, a feature module is an NgModule class that is dedicated to an application feature or workflow.
+Technically, it's another class adorned by the `@NgModule` decorator, just like a root `AppModule`.
-The root module and the feature module share the same execution context.
-They share the same dependency injector, which means the services in one module
-are available to all.
+Feature module metadata have the same properties as root module metadata.
+When loaded together, the root module and the feature module share the same dependency injector,
+which means the services provided in a feature module are available to all.
-The modules have the following significant technical differences:
+These two module types have the following significant technical differences:
* You _boot_ the root module to _launch_ the app;
you _import_ a feature module to _extend_ the app.
-* A feature module can expose or hide its implementation from other modules.
+* A feature module can expose or hide its [declarables](#declarables) from other NgModules.
Otherwise, a feature module is distinguished primarily by its intent.
A feature module delivers a cohesive set of functionality
focused on an application business domain, user workflow, facility (forms, http, routing),
or collection of related utilities.
+Feature modules help you partition the app into areas of specific interest and purpose.
-While you can do everything within the root module,
-feature modules help you partition the app into areas of specific interest and purpose.
-
-
-A feature module collaborates with the root module and with other modules
+A feature module collaborates with the root module and with other NgModules
through the services it provides and
the components, directives, and pipes that it shares.
-In the next section, you'll carve the contact functionality out of the root module
-and into a dedicated feature module.
-
-
{@a contact-module-v1}
+Make contact editor a feature
-### Make _Contact_ a feature module
-
+In this section, you refactor the _contact editor_ functionality out of the root `AppModule`
+and into a dedicated feature module by following these steps.
-It's easy to refactor the contact material into a contact feature module.
-
-1. Create the `ContactModule` in the `src/app/contact` folder.
-1. Move the contact material from `AppModule` to `ContactModule`.
-1. Replace the imported `BrowserModule` with `CommonModule`.
+1. Create the `ContactModule` feature module in its own folder.
+1. Copy the _contact editor_ declarations and providers from `AppModule` to `ContactModule`.
+1. Export the `ContactComponent`.
1. Import the `ContactModule` into the `AppModule`.
+1. Cleanup the `AppModule`.
-`AppModule` is the only existing class that changes. But you do add one new file.
+You'll create one new `ContactModule` class and change one existing `AppModule` class.
+All other files are untouched.
-### Add the _ContactModule_
+### Create the feature module
-Here's the new `ContactModule`:
-
-
+Generate the _ContactModule_ and its folder with an Angular CLI command.
+
+ng generate module contact
+Here's the generated `ContactModule`.
+
+
-You copy from `AppModule` the contact-related import statements and `@NgModule` properties
-that concern the contact, and paste them into `ContactModule`.
+After modifying the initial `ContactsModule` as outlined above, it looks like this.
-You _import_ the `FormsModule` because the contact component needs it.
+
+
-
+The following sections discuss the important changes.
+### Import _CommonModule_
+Notice that `ContactModule` imports `CommonModule`, not `BrowserModule`.
+The CLI module generation took care of this for you.
-Modules don't inherit access to the components, directives, or pipes that are declared in other modules.
-What `AppModule` imports is irrelevant to `ContactModule` and vice versa.
-Before `ContactComponent` can bind with `[(ngModel)]`, its `ContactModule` must import `FormsModule`.
+Feature module components need the common Angular directives but
+not the services and bootstrapping logic in `BrowserModule`.
+See the [NgModule FAQs](guide/ngmodule-faq#q-browser-vs-common-module)
+for more details.
+
+### Import _FormsModule_
+
+The `ContactModule` imports the `FormsModule`
+because its `ContactComponent` uses `NgModel`,
+one of the `FormsModule` directives.
+
+
+
+NgModules don't inherit access to the declarations of the root `AppModule` or any other NgModule.
+Each NgModule must import what it needs.
+Because `ContactComponent` needs the form directives,
+its `ContactModule` must import `FormsModule`.
+
Copy declarations
+The `ContactModule` declares the _contact editor_ components, directives and pipes.
-You also replaced `BrowserModule` by `CommonModule`, for reasons explained in the
-[Should I import BrowserModule or CommonModule?](guide/ngmodule-faq#q-browser-vs-common-module)
-section of the [NgModule FAQs](guide/ngmodule-faq) page.
+
-You _declare_ the contact component, directive, and pipe in the module `declarations`.
+The app fails to compile at this point, in part because
+`ContactComponent` is currently declared in both the `AppModule` and the `ContactModule`.
+A component may only be declared in one NgModule.
+You'll fix this problem shortly.
-You _export_ the `ContactComponent` so
-other modules that import the `ContactModule` can include it in their component templates.
+
-All other declared contact classes are private by default.
-The `AwesomePipe` and `HighlightDirective` are hidden from the rest of the application.
-The `HighlightDirective` can no longer color the `AppComponent` title text.
+{@a root-scoped-providers}
+### Providers are root-scoped
+The `ContactModule` provides the `ContactService` and the `AppModule` will stop providing it [after refactoring](#refactor-appmodule).
+
+Architecturally, the `ContactService` belongs to the _contact editor_ domain.
+Classes in the rest of the app do not need the `ContactService` and shouldn't inject it.
+So it makes sense for the `ContactModule` to provide the `ContactService` as it does.
+
+You might expect that the `ContactService` would only be injectable in classes declared or provided in the `ContactModule`.
+
+That's not the case.
+_Any_ class _anywhere_ can inject the `ContactService`
+because `ContactModule` providers are _root_-scoped.
+
+
+
+To be precise, all _eagerly loaded_ modules— modules loaded when the application starts — are root-scoped.
+This `ContactModule` is eagerly loaded.
+
+You will learn that services provided in [_lazy-loaded_ modules](#lazy-loaded-modules)
+have their own scope.
+
+
+
+Angular does not have _module_-scoping mechanism.
+Unlike components, NgModule instances do not have their own injectors
+so they can't have their own provider scopes.
+
+`ContactService` remains an _application_-scoped service because Angular
+registers all NgModule `providers` with the application's *root injector*.
+This is true whether the service is provided directly in the root `AppModule`
+or in an imported feature module like `ContactModule`.
+
+In practice, service scoping is rarely an issue.
+Components don't accidentally inject a service.
+To inject the `ContactService`, you'd have to import its _type_
+and explicitly inject the service into a class constructor.
+Only _contact editor_ components should import the `ContactService` type.
+
+If it's really important to you to restrict the scope of a service,
+provide it in the feature's top-level component (`ContactComponent` in this case).
+
+For more on this topic, see "[How do I restrict service scope to a module?](guide/ngmodule-faq#q-component-scoped-providers)"
+in the [NgModule FAQs](guide/ngmodule-faq).
+
+### Export public-facing components
+
+The `ContactModule` makes the `ContactComponent` _public_ by _exporting_ it.
+
+
+
+
+Declared classes are _private_ by default.
+Private [declarables](#declarables) may only appear in the templates of components declared by the _same_ NgModule.
+They are invisible to components in _other_ NgModules.
+
+That's a problem for the `AppComponent`.
+Both components _used to be_ declared in `AppModule` so Angular could
+display the `ContactComponent` within the `AppComponent`.
+Now that the `ContactComponent` is declared in its own feature module.
+The `AppComponent` cannot see it unless it is public.
+
+The first step toward a solution is to _export_ the `ContactComponent`.
+The second step is to _import_ the `ContactModule` in the `AppModule`,
+which you'll do when you [refactor the _AppModule_](#refactor-appmodule).
+
+The `AwesomePipe` and `ContactHighlightDirective` remain private and are hidden from the rest of the application.
+
+The `ContactHighlightDirective`, being private, no longer overrides the `HighlightDirective` in the `AppComponent`. The background of the title text is gold as intended.
+
+{@a refactor-appmodule}
### Refactor the _AppModule_
-Return to the `AppModule` and remove everything specific to the contact feature set.
-
-* Delete the contact import statements.
-* Delete the contact declarations and contact providers.
-* Delete the `FormsModule` from the `imports` list (`AppComponent` doesn't need it).
+Return to the `AppModule` and remove everything specific to the _contact editor_ feature set.
Leave only the classes required at the application root level.
-Then import the `ContactModule` so the app can continue to display the exported `ContactComponent`.
+* Delete the _contact editor_ import statements.
+* Delete the _contact editor_ declarations and providers.
+* Delete the `FormsModule` from the `imports` list (the `AppComponent` doesn't need it).
+* Import the `ContactModule` so the app can continue to display the exported `ContactComponent`.
-Here's the refactored version of the `AppModule` along with the previous version.
+Here's the refactored `AppModule`, presented side-by-side with the previous version.
-
-
+
-
-
+
-
-
### Improvements
There's a lot to like in the revised `AppModule`.
* It does not change as the _Contact_ domain grows.
-* It only changes when you add new modules.
+* It only changes when you add new NgModules.
* It's simpler:
* Fewer import statements.
* No `FormsModule` import.
- * No contact-specific declarations.
+ * No _contact editor_ declarations.
* No `ContactService` provider.
- * No `HighlightDirective` conflict.
+ * No _highlight directive_ conflicts.
Try this `ContactModule` version of the sample.
Try the live example.
+{@a routing-modules}
+{@a lazy-loaded-modules}
-{@a lazy-load}
+## Routing modules
+Navigating the app with the [Angular Router](guide/router) reveals
+new dimensions of the NgModule.
+In this segment, you'll learn to write _routing modules_ that configure the router.
+You'll discover the implications of _lazy loading_ a feature module with the router's `loadChildren` method.
-## Lazy-loading modules with the router
+Imagine that the sample app has evolved substantially along the lines of the
+[Tour of Heroes tutorial](tutorial).
-The Heroic Staffing Agency sample app has evolved.
-It has two more modules, one for managing the heroes on staff and another for matching crises to the heroes.
-Both modules are in the early stages of development.
-Their specifics aren't important to the story and this page doesn't discuss every line of code.
+* The app has three feature modules: Contact, Hero (new), and Crisis (new).
+* The [Angular router](guide/router) helps users navigate among these modules.
+* The `ContactComponent` is the default destination when the app starts.
+* The `ContactModule` continues to be _eagerly loaded_ when the application starts.
+* `HeroModule` and the `CrisisModule` are _lazy-loaded_.
-
+There's too much code behind this sample app to review every line.
+Instead, the guide explores just those parts necessary to understand new aspects of NgModules.
-
-
-Examine and download the complete source for this version from
+You can examine the complete source for this version of the app in
the live example.
-
-
-
-
-Some facets of the current application merit discussion are as follows:
-
-* The app has three feature modules: Contact, Hero, and Crisis.
-* The Angular router helps users navigate among these modules.
-* The `ContactComponent` is the default destination when the app starts.
-* The `ContactModule` continues to be "eagerly" loaded when the application starts.
-* `HeroModule` and the `CrisisModule` are lazy loaded.
-
{@a app-component-template}
-The new `AppComponent` template has
+
+
The root AppComponent
+
+The revised `AppComponent` template has
a title, three links, and a `
`.
-
+The `` element that displayed the `ContactComponent` is gone; you're routing to the _Contact_ page now.
+The root AppModule
-The `` element is gone; you're routing to the _Contact_ page now.
-
-The `AppModule` has changed modestly:
+The `AppModule` is slimmer now.
-
+The `AppModule` is no longer aware of the application domains such as contacts, heroes, and crises.
+Those concerns are pushed down to `ContactModule`, `HeroesModule`, and `CrisisModule` respectively
+and only the routing configuration knows about them.
-
-
-
-
-
-Some file names bear a `.3` extension that indicates
-a difference with prior or future versions.
-The significant differences will be explained in due course.
-
-
-
-
-
-
-
-The module still imports `ContactModule` so that its routes and components are mounted when the app starts.
-
-The module does _not_ import `HeroModule` or `CrisisModule`.
-They'll be fetched and mounted asynchronously when the user navigates to one of their routes.
-
-The significant change from version 2 is the addition of the *AppRoutingModule* to the module `imports`.
+The significant change from version 2 is the addition of the *AppRoutingModule* to the NgModule `imports`.
The `AppRoutingModule` is a [routing module](guide/router#routing-module)
that handles the app's routing concerns.
-### App routing
+### _AppRoutingModule_
-
+The router is the subject of the [Routing & Navigation](guide/router) guide, so this section skips many routing details and
+concentrates on the _intersection_ of NgModules and routing.
+You can specify router configuration directly within the root `AppModule` or within a feature module.
+
+The _Router guide_ recommends instead that you locate router configuration in separate, dedicated NgModules, called _routing modules_.
+You then import those routing modules into their corresponding root or feature modules.
+
+The goal is to separate the normal declarative concerns of an NgModule from the often complex router configuration logic.
+
+By convention, a routing module's name ends in `...RoutingModule`.
+The top-level root module is `AppModule` and it imports its companion _routing module_ called `AppRoutingModule`.
+
+
+Here is this app's `AppRoutingModule`, followed by a discussion.
+
+
-The router is the subject of the [Routing & Navigation](guide/router) page, so this section skips many of the details and
-concentrates on the intersection of NgModules and routing.
+The `AppRoutingModule` defines three routes:
-The `app-routing.module.ts` file defines three routes.
+
+
The first route redirects the empty URL (such as `http://host.com/`)
to another route whose path is `contact` (such as `http://host.com/contact`).
-The `contact` route isn't defined here.
-It's defined in the _Contact_ feature's _own_ routing module, `contact-routing.module.ts`.
-It's standard practice for feature modules with routing components to define their own routes.
-You'll get to that file in a moment.
-
-The remaining two routes use lazy loading syntax to tell the router where to find the modules:
-
-
-
-
-
-
+The `contact` route isn't defined within the `AppRoutingModule`.
+It's defined in the _Contact_ feature's _own_ routing module, `ContactRoutingModule`.
-
-
-A lazy-loaded module location is a _string_, not a _type_.
-In this app, the string identifies both the module _file_ and the module _class_,
-the latter separated from the former by a `#`.
-
+It's standard practice for feature modules with routing components to define their own routes.
+You'll get to [`ContactRoutingModule`](#contact-routing-module) in a moment.
+The remaining two routes use lazy loading syntax to tell the router where to find the modules for the hero and crisis features:
-
-### RouterModule.forRoot
-
-The `forRoot` static class method of the `RouterModule` with the provided configuration and
-added to the `imports` array provides the routing concerns for the module.
-
-
-
+
+
+A lazy-loaded NgModule location is a _string_, not a _type_.
+In this app, the string identifies both the NgModule _file_ and the NgModule _class_,
+the latter separated from the former by a `#`.
-The returned `AppRoutingModule` class is a `Routing Module` containing both the `RouterModule` directives
-and the dependency-injection providers that produce a configured `Router`.
+
-This `AppRoutingModule` is intended for the app _root_ module only.
+### Routing module imports
+A _routing module_ typically imports the Angular `RouterModule` so it can register routes.
+
+It may also import a _feature module_ which registers routes (either directly or through its companion _routing module_).
+
+This `AppRoutingModule` does both.
+
+
+
+
+It first imports the `ContactModule`, which [as you'll see](#contact-routing-module),
+imports its own `ContactRoutingModule`.
+
+**Import order matters!**
+Because "contacts" is the first defined route and the default route for the app,
+you must import it _before_ all other routing-related modules.
+
+The second import registers the routes defined in this module
+by calling the `RouterModule.forRoot` class method.
+
+
+
+
+The `forRoot` method does two things:
+
+1. Configures the router with the supplied _routes_.
+1. Initializes the Angular router itself.
+Call `RouterModule.forRoot` exactly once for the entire app.
+Calling it in the `AppRoutingModule`, the companion to the root `AppModule`,
+is a good way to ensure that this method is called exactly once.
-Never call `RouterModule.forRoot` in a feature-routing module.
+Never call `RouterModule.forRoot` in a feature's _routing module_.
+### Re-export _RouterModule_
+All _routing modules_ should re-export the `RouterModule`.
-Back in the root `AppModule`, add the `AppRoutingModule` to its `imports` list,
-and the app is ready to navigate.
-
-
-
+
+Re-exporting `RouterModule` makes the router directives
+available to the companion module that imports it.
+This is a considerable convenience for the importing module.
+For example, the `AppComponent` template relies on the
+[`routerLink`](guide/router#router-links) directive
+to turn the user's clicks into navigations.
+The Angular compiler only recognizes `routerLink` because
+
+- `AppComponent`is declared by `AppModule`,
+- `AppModule` imports `AppRoutingModule`,
+- `AppRoutingModule` exports `RouterModule`, and
+- `RouterModule` exports the `RouterLink` directive.
+
+If `AppRoutingModule` didn't re-export `RouterModule`, the `AppModule` would have to import the `RouterModule` itself.
+
+{@a contact-routing-module}
### Routing to a feature module
-The `src/app/contact` folder holds a new file, `contact-routing.module.ts`.
-It defines the `contact` route mentioned earlier and provides a `ContactRoutingModule` as follows:
+
+The three feature modules (`ContactModule`, `HeroModule`, `CrisisModule`)
+have corresponding routing modules (`ContactRoutingModule`, `HeroRoutingModule`, `CrisisRoutingModule`).
+
+They follow the same pattern as the `AppRoutingModule`.
+* define routes
+* register the routes with Angular's `RouterModule`
+* export the `RouterModule`.
+
+The `ContactRoutingModule` is the simplest of the three.
+It defines and registers a single route to the `ContactComponent`.
-
-
-
-This time you pass the route list to the `forChild` method of the `RouterModule`.
-The route list is only responsible for providing additional routes and is intended for feature modules.
-
+There is **one critical difference** from `AppRoutingModule`:
+you pass the routes to `RouterModule.forChild`, not `forRoot`.
-
-
Always call `RouterModule.forChild` in a feature-routing module.
-
+Never call `RouterModule.forRoot`.
+#### _ContactModule_ changes
-
+Because the app navigates to the `ContactComponent` instead of
+simply displaying it in the `AppComponent` template,
+the `ContactModule` has changed.
+* It imports the `ContactRoutingModule`.
+* It no longer exports `ContactComponent`.
-_forRoot_ and _forChild_ are conventional names for methods that
-deliver different `import` values to root and feature modules.
-Angular doesn't recognize them but Angular developers do.
+The `ContactComponent` is only displayed by the router,
+No template references its `
` selector.
+There's no reason to make it public via the `exports` array.
-[Follow this convention](guide/ngmodule-faq#q-for-root) if you write a similar module
-that has both shared [declarables](guide/ngmodule-faq#q-declarable) and services.
-
-
-
-
-
-
-`ContactModule` has changed in two small but important ways.
+Here is the latest version, side-by-side with the previous version.
-
-
+
-
-
+
-
-* It imports the `ContactRoutingModule` object from `contact-routing.module.ts`.
-* It no longer exports `ContactComponent`.
-
-Now that you navigate to `ContactComponent` with the router, there's no reason to make it public.
-Also, `ContactComponent` doesn't need a selector.
-No template will ever again reference this `ContactComponent`.
-It's gone from the [AppComponent template](guide/ngmodule#app-component-template).
-
-
{@a hero-module}
+### Lazy-loaded routing
-### Lazy-loaded routing to a module
+The `HeroModule` and `CrisisModule` have corresponding _routing modules_, `HeroRoutingModule` and `CrisisRoutingModule`.
-The lazy-loaded `HeroModule` and `CrisisModule` follow the same principles as any feature module.
-They don't look different from the eagerly loaded `ContactModule`.
+The app _lazy loads_ the `HeroModule` and the `CrisisModule`.
+That means the `HeroModule` and the `CrisisModule` are not loaded into the browser until the user navigates to their components.
-The `HeroModule` is a bit more complex than the `CrisisModule`, which makes it
-a more interesting and useful example. Its file structure is as follows:
+
+Do not import the `HeroModule` or `CrisisModule` or any of their classes outside of their respective file folders.
+If you do, you will unintentionally load those modules and all of their code
+when the application starts, defeating the purpose of lazy loading.
-
-
-
- hero
-
-
-
-
-
- hero-detail.component.ts
-
-
-
- hero-list.component.ts
-
-
-
- hero.component.ts
-
-
-
- hero.module.ts
-
-
-
- hero-routing.module.ts
-
-
-
- hero.service.ts
-
-
-
- highlight.directive.ts
-
-
-
+For example, if you import the `HeroService` in `AppModule`,
+the `HeroService` class and all related hero classes will be loaded when the application starts.
+Lazy loading can improve the app's perceived performance because the browser doesn't have to process lazy-loaded code when the app starts.
+It may _never_ process that code.
+You cannot tell that these modules are lazy-loaded by looking at their _routing modules_.
+They happen to be a little more complex than `ContactRoutingModule`.
+For example, The `HeroRoutingModule` has [child routes](guide/router#child-routing-component).
+But the added complexity springs from intrinsic hero and crisis functionality, not from lazy loading.
+Fundamentally, these _routing modules_ are just like `ContactRoutingModule` and you write them the same way.
-This is the child routing scenario familiar to readers of the
-[Child routing component](guide/router#child-routing-component) section of the
-[Routing & Navigation](guide/router#child-routing-component) page.
-The `HeroComponent` is the feature's top component and routing host.
-Its template has a `
` that displays either a list of heroes (`HeroList`)
-or an editor of a selected hero (`HeroDetail`).
-Both components delegate to the `HeroService` to fetch and save data.
+{@a lazy-load-DI}
+### Lazy-loaded NgModule providers
-Yet another `HighlightDirective` colors elements in yet a different shade.
-In the next section, [Shared modules](guide/ngmodule#shared-module "Shared modules"), you'll resolve the repetition and inconsistencies.
+There is a **runtime difference** that can be significant.
+Services provided by lazy-loaded NgModules are only available to classes instantiated within the lazy-loaded context. The reason has to do with dependency injection.
-The `HeroModule` is a feature module like any other.
+When an NgModule is _eagerly loaded_ as the application starts,
+its providers are added to the application's _root injector_.
+Any class in the application can inject a service from the _root injector_.
-
+When the router _lazy loads_ an NgModule, Angular instantiates the module
+with a _child injector_ (a descendant of the _root injector_)
+and adds the module's providers to this _child injector_.
+Classes created with the _child injector_ can inject one of its provided services.
+Classes created with _root injector_ cannot.
+Each of the three feature modules has its own data access service.
+Because the `ContactModule` is _eagerly loaded_ when the application starts,
+its `ContactService` is provided by the application's _root dependency injector_.
+That means the `ContactService` can be injected into any application class, including hero and crisis components.
+
+Because `CrisisModule` is _lazy-loaded_,
+its `CrisisService` is provided by the `CrisisModule` _child injector_.
+It can only be injected into one of the crisis components.
+No other kind of component can inject the `CrisisService` because no other kind of component can be reached along a route that lazy loads the `CrisisModule`.
+
+### Lazy-loaded NgModule lifetime
+
+Both eager and lazy-loaded NgModules are created _once_ and never destroyed.
+This means that their provided service instances are created _once_ and never destroyed.
+
+As you navigate among the application components, the router creates and destroys instances of the contact, hero, and crisis components.
+When these components inject data services provided by their modules,
+they get the same data service instance each time.
+
+If the `HeroService` kept a cache of unsaved changes and the user navigated to the `ContactComponent` or the `CrisisListComponent`, the pending hero changes would remain in the one `HeroService` instance, waiting to be saved.
+
+But if you provided the `HeroService` in the `HeroComponent` instead of the `HeroModule`, new `HeroService` instances would be created each time
+the user navigated to a hero component. Previously pending hero changes would be lost.
+
+To illustrate this point, the sample app provides the `HeroService` in the `HeroComponent` rather than the `HeroModule`.
+
+Run the app, open the browser development tools, and look at the console as you navigate among the feature pages.
+
+
+// App starts
+ContactService instance created.
+...
+// Navigate to Crisis Center
+CrisisService instance created.
+...
+// Navigate to Heroes
+HeroService instance created.
+...
+// Navigate to Contact
+HeroService instance destroyed.
+...
+// Navigate back to Heroes
+HeroService instance created.
+The console log shows the `HeroService` repeatedly created and destroyed.
+The `ContactService` and `CrisisService` are created but never destroyed, no matter where you navigate.
+#### Run it
-It imports the `FormsModule` because the `HeroDetailComponent` template binds with `[(ngModel)]`.
-It imports the `HeroRoutingModule` from `hero-routing.module.ts` just as `ContactModule` and `CrisisModule` do.
-
-The `CrisisModule` is much the same.
+Try this routed version of the sample.
Try the live example.
-
{@a shared-module}
-
-
## Shared modules
The app is shaping up.
-But it carries three different versions of the `HighlightDirective`.
-And the many files cluttering the app folder level could be better organized.
+But there are a few annoying problems.
+There are three unnecessarily different _highlight directives_
+and the many files cluttering the app folder level could be better organized.
-Add a `SharedModule` to hold the common components, directives, and pipes
-and share them with the modules that need them.
+You can eliminate the duplication and tidy-up by writing a `SharedModule`
+to hold the common components, directives, and pipes.
+Then share this NgModule with the other NgModules that need these declarables.
-1. Create an `src/app/shared` folder.
-1. Move the `AwesomePipe` and `HighlightDirective` from `src/app/contact` to `src/app/shared`.
-1. Delete the `HighlightDirective` classes from `src/app/` and `src/app/hero`.
-1. Create a `SharedModule` class to own the shared material.
-1. Update other feature modules to import `SharedModule`.
-
-Here is the `SharedModule`:
-
-
+Use the CLI to create the `SharedModule` class in its `src/app/shared` folder.
+
+ng generate module shared
+Now refactor as follows:
+- Move the `AwesomePipe` from `src/app/contact` to `src/app/shared`.
+- Move the `HighlightDirective` from `src/app/hero` to `src/app/shared`.
+- Delete the _highlight directive_ classes from `src/app/` and `src/app/contact`.
+- Update the `SharedModule` as follows:
+
+
+
Note the following:
-* It imports the `CommonModule` because its component needs common directives.
-* It declares and exports the utility pipe, directive, and component classes as expected.
-* It re-exports the `CommonModule` and `FormsModule`
+* It declares and exports the shared pipe and directive.
+* It imports and re-exports the `CommonModule` and `FormsModule`
+* It can re-export `FormsModule` without importing it.
-### Re-exporting other modules
+### Re-exporting NgModules
-If you review the application, you may notice that many components requiring `SharedModule` directives
-also use `NgIf` and `NgFor` from `CommonModule`
-and bind to component properties with `[(ngModel)]`, a directive in the `FormsModule`.
-Modules that declare these components would have to import `CommonModule`, `FormsModule`, and `SharedModule`.
+Technically, there is no need for `SharedModule` to import `CommonModule` or `FormsModule`.
+`SharedModule` doesn't declare anything that needs material from `CommonModule` or `FormsModule`.
-You can reduce the repetition by having `SharedModule` re-export `CommonModule` and `FormsModule`
-so that importers of `SharedModule` get `CommonModule` and `FormsModule` for free.
+But NgModules that would like to import `SharedModule` for its pipe and highlight directive happen also to declare components that need `NgIf` and `NgFor` from `CommonModule`
+and do two-way binding with `[(ngModel)]` from the `FormsModule`.
-As it happens, the components declared by `SharedModule` itself don't bind with `[(ngModel)]`.
-Technically, there is no need for `SharedModule` to import `FormsModule`.
+Normally, they'd have to import `CommonModule` and `FormsModule` as well as `SharedModule`.
+Now they can just import `SharedModule`.
+By exporting `CommonModule` and `FormsModule`,
+`SharedModule` makes them available to its importers _for free_.
+
+#### A trimmer _ContactModule_
+
+See how `ContactModule` became more concise, compared to its previous version:
+
+
+
+
+
+
+
+
+
+
+
+Notice the following:
+
+* The `AwesomePipe` and `ContactHighlightDirective` are gone.
+* The imports include `SharedModule` instead of `CommonModule` and `FormsModule`.
+* The new version is leaner and cleaner.
-`SharedModule` can still export `FormsModule` without listing it among its `imports`.
### Why _TitleComponent_ isn't shared
`SharedModule` exists to make commonly used components, directives, and pipes available
-for use in the templates of components in many other modules.
+for use in the templates of components in many other NgModules.
The `TitleComponent` is used only once by the `AppComponent`.
There's no point in sharing it.
-
{@a no-shared-module-providers}
-
### Why _UserService_ isn't shared
While many components share the same service instances,
-they rely on Angular dependency injection to do this kind of sharing, not the module system.
+they rely on Angular dependency injection to do this kind of sharing, not the NgModule system.
Several components of the sample inject the `UserService`.
There should be only one instance of the `UserService` in the entire application
and only one provider of it.
`UserService` is an application-wide singleton.
-You don't want each module to have its own separate instance.
+You don't want each NgModule to have its own separate instance.
Yet there is [a real danger](guide/ngmodule-faq#q-why-bad) of that happening
-
if the `SharedModule` provides the `UserService`.
-
-
-
Do *not* specify app-wide singleton `providers` in a shared module.
-A lazy-loaded module that imports that shared module makes its own copy of the service.
-
+A lazy-loaded NgModule that imports that shared module makes its own copy of the service.
-
-
{@a core-module}
-
-
## The Core module
+
At the moment, the root folder is cluttered with the `UserService`
and `TitleComponent` that only appear in the root `AppComponent`.
You didn't include them in the `SharedModule` for reasons just explained.
@@ -1280,45 +1248,37 @@ and never import anywhere else.
Perform the following steps:
-1. Create an `src/app/core` folder.
-* Move the `UserService` and `TitleComponent` from `src/app/` to `src/app/core`.
-* Create a `CoreModule` class to own the core material.
-* Update the `AppRoot` module to import `CoreModule`.
+1. Create a `CoreModule` class in an `src/app/core` folder.
+1. Move the `TitleComponent` and `UserService` from `src/app/` to `src/app/core`.
+1. Declare and export the `TitleComponent`.
+1. Provide the `UserService`.
+1. Update the root `AppModule` to import `CoreModule`.
Most of this work is familiar. The interesting part is the `CoreModule`.
-
-
+
-
-
-
-
You're importing some extra symbols from the Angular core library that you're not using yet.
They'll become relevant later in this page.
-
-
The `@NgModule` metadata should be familiar.
-You declare the `TitleComponent` because this module owns it and you export it
-because `AppComponent` (which is in `AppModule`) displays the title in its template.
+You declare the `TitleComponent` because this NgModule owns it.
+You export it because `AppComponent` (which is in `AppModule`) displays the title in its template.
`TitleComponent` needs the Angular `NgIf` directive that you import from `CommonModule`.
`CoreModule` provides the `UserService`. Angular registers that provider with the app root injector,
making a singleton instance of the `UserService` available to any component that needs it,
whether that component is eagerly or lazily loaded.
-
-
-
Why bother?
+
This scenario is clearly contrived.
The app is too small to worry about a single service file and a tiny, one-time component.
@@ -1337,81 +1297,41 @@ Each must be registered exactly once, in the app root injector, when the applica
While many components inject such services in their constructors—and
therefore require JavaScript `import` statements to import their symbols—no
-other component or module should define or re-create the services themselves.
+other component or NgModule should define or re-create the services themselves.
Their _providers_ aren't shared.
We recommend collecting such single-use classes and hiding their details inside a `CoreModule`.
A simplified root `AppModule` imports `CoreModule` in its capacity as orchestrator of the application as a whole.
-
-
-
-
-## Cleanup
-Having refactored to a `CoreModule` and a `SharedModule`, it's time to clean up the other modules.
-
-### A trimmer _AppModule_
+#### A trimmer _AppModule_
Here is the updated `AppModule` paired with version 3 for comparison:
-
-
-
-
`AppModule` now has the following qualities:
-* A little smaller because many `src/app/root` classes have moved to other modules.
-* Stable because you'll add future components and providers to other modules, not this one.
-* Delegated to imported modules rather than doing work.
+* A little smaller because many `src/app/root` classes have moved to other NgModules.
+* Stable because you'll add future components and providers to other NgModules, not this one.
+* Delegated to imported NgModules rather than doing work.
* Focused on its main task, orchestrating the app as a whole.
-### A trimmer _ContactModule_
-Here is the new `ContactModule` paired with the prior version:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Notice the following:
-
-* The `AwesomePipe` and `HighlightDirective` are gone.
-* The imports include `SharedModule` instead of `CommonModule` and `FormsModule`.
-* The new version is leaner and cleaner.
-
-
-
-
-
{@a core-for-root}
+### Configure core services with _CoreModule.forRoot_
-
-## Configure core services with _CoreModule.forRoot_
-
-A module that adds providers to the application can offer a facility for configuring those providers as well.
+An NgModule that adds providers to the application can offer a facility for configuring those providers as well.
By convention, the `forRoot` static method both provides and configures services at the same time.
It takes a service configuration object and returns a
@@ -1425,85 +1345,57 @@ The root `AppModule` imports the `CoreModule` and adds the `providers` to the `A
-
-
More precisely, Angular accumulates all imported providers before appending the items listed in `@NgModule.providers`.
This sequence ensures that whatever you add explicitly to the `AppModule` providers takes precedence
-over the providers of imported modules.
+over the providers of imported NgModules.
-
-
Add a `CoreModule.forRoot` method that configures the core `UserService`.
You've extended the core `UserService` with an optional, injected `UserServiceConfig`.
If a `UserServiceConfig` exists, the `UserService` sets the user name from that config.
-
-
-
Here's `CoreModule.forRoot` that takes a `UserServiceConfig` object:
-
-
-
Lastly, call it within the `imports` list of the `AppModule`.
-
-
-
The app displays "Miss Marple" as the user instead of the default "Sherlock Holmes".
-
-
-
-Call `forRoot` only in the root application module, `AppModule`.
-Calling it in any other module, particularly in a lazy-loaded module,
+Call `forRoot` only in the root module, `AppModule`.
+Calling it in any other NgModule, particularly in a lazy-loaded NgModule,
is contrary to the intent and can produce a runtime error.
Remember to _import_ the result; don't add it to any other `@NgModule` list.
-
-
-
-
-
-
+
{@a prevent-reimport}
-
-
-## Prevent reimport of the _CoreModule_
+### Prevent reimport of the _CoreModule_
Only the root `AppModule` should import the `CoreModule`.
-[Bad things happen](guide/ngmodule-faq#q-why-bad) if a lazy-loaded module imports it.
-
+[Bad things happen](guide/ngmodule-faq#q-why-bad) if a lazy-loaded NgModule imports it.
You could hope that no developer makes that mistake.
Or you can guard against it and fail fast by adding the following `CoreModule` constructor.
-
-
-
The constructor tells Angular to inject the `CoreModule` into itself.
That seems dangerously circular.
@@ -1519,9 +1411,9 @@ The `@Optional` decorator means not finding the service is OK.
The injector returns `null`, the `parentModule` parameter is null,
and the constructor concludes uneventfully.
-It's a different story if you improperly import `CoreModule` into a lazy-loaded module such as `HeroModule` (try it).
+It's a different story if you improperly import `CoreModule` into a lazy-loaded NgModule such as `HeroModule` (try it).
-Angular creates a lazy-loaded module with its own injector, a _child_ of the root injector.
+Angular creates a lazy-loaded NgModule with its own injector, a _child_ of the root injector.
`@SkipSelf` causes Angular to look for a `CoreModule` in the parent injector, which this time is the root injector.
Of course it finds the instance imported by the root `AppModule`.
Now `parentModule` exists and the constructor throws the error.
diff --git a/aio/content/navigation.json b/aio/content/navigation.json
index 137de17ce5..5c66e7a999 100644
--- a/aio/content/navigation.json
+++ b/aio/content/navigation.json
@@ -225,17 +225,17 @@
{
"title": "NgModules",
- "tooltip": "Learn how to use NgModules to make your apps efficient.",
+ "tooltip": "Modularize your app with NgModules.",
"children": [
{
"url": "guide/ngmodule",
"title": "NgModules",
- "tooltip": "Define application modules with @NgModule."
+ "tooltip": "Define application modules with the NgModule."
},
{
"url": "guide/ngmodule-faq",
"title": "NgModule FAQs",
- "tooltip": "Answers to frequently asked questions about @NgModule."
+ "tooltip": "Answers to frequently asked questions about NgModules."
}
]},