
committed by
Alex Eagle

parent
e64b1e99c2
commit
53f91189a1
@ -1076,7 +1076,7 @@ The Angular code is shown using TypeScript.
|
||||
* `imports`: specifies the list of other modules that this module depends upon
|
||||
* `declaration`: keeps track of your components, pipes, and directives.
|
||||
|
||||
For more information on modules, see [NgModules](guide/ngmodule).
|
||||
For more information on modules, see [NgModules](guide/ngmodules).
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@ -578,7 +578,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 [NgModules](guide/ngmodule).
|
||||
for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodules).
|
||||
|
||||
{@ metadata-rewriting}
|
||||
### Metadata rewriting
|
||||
|
@ -34,7 +34,8 @@ You'll learn the details in the pages that follow. For now, focus on the big pic
|
||||
Angular apps are modular and Angular has its own modularity system called _NgModules_.
|
||||
|
||||
NgModules are a big deal.
|
||||
This page introduces modules; the [NgModules](guide/ngmodule) page covers them in depth.
|
||||
This page introduces modules; the [NgModules](guide/ngmodules) pages
|
||||
relating to NgModules covers them in detail.
|
||||
|
||||
<br class="clear">
|
||||
|
||||
@ -139,7 +140,7 @@ Hang in there. The confusion yields to clarity with time and experience.
|
||||
|
||||
<div class="l-sub-section">
|
||||
|
||||
Learn more from the [NgModules](guide/ngmodule) page.
|
||||
Learn more from the [NgModules](guide/ngmodules) page.
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -53,7 +53,7 @@ The CLI creates `src/app/highlight.directive.ts`, a corresponding test file (`..
|
||||
|
||||
<div class="l-sub-section">
|
||||
|
||||
_Directives_ must be declared in [Angular Modules](guide/ngmodule) in the same manner as _components_.
|
||||
_Directives_ must be declared in [Angular Modules](guide/ngmodules) in the same manner as _components_.
|
||||
|
||||
</div >
|
||||
|
||||
|
@ -1,169 +1,181 @@
|
||||
# Bootstrapping
|
||||
|
||||
An Angular Module (NgModule) class describes how the application parts fit together.
|
||||
Every application has at least one Angular Module, the _root_ module
|
||||
that you [bootstrap](#main) to launch the application.
|
||||
You can call the class anything you want. The conventional name is `AppModule`.
|
||||
#### Prerequisites
|
||||
|
||||
The [**Angular CLI**](https://cli.angular.io/) produces a new project with the following minimal `AppModule`.
|
||||
You evolve this module as your application grows.
|
||||
A basic understanding of the following:
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
|
||||
<code-example path="cli-quickstart/src/app/app.module.ts" title="src/app/app.module.ts" linenums="false">
|
||||
</code-example>
|
||||
<hr />
|
||||
|
||||
An NgModule describes how the application parts fit together.
|
||||
Every application has at least one Angular module, the _root_ module
|
||||
that you bootstrap to launch the application.
|
||||
By convention, it is usually called `AppModule`.
|
||||
|
||||
After the `import` statements, you come to a class adorned with the
|
||||
**`@NgModule`** [_decorator_](guide/glossary#decorator '"Decorator" explained').
|
||||
If you use the CLI to generate an app, the default `AppModule` is as follows:
|
||||
|
||||
```javascript
|
||||
/* JavaScript imports */
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
/* the AppModule class with the @NgModule decorator */
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
|
||||
```
|
||||
|
||||
After the import statements is a class with the
|
||||
**`@NgModule`** [decorator](guide/glossary#decorator '"Decorator" explained').
|
||||
|
||||
The `@NgModule` decorator identifies `AppModule` as an `NgModule` class.
|
||||
`@NgModule` takes a _metadata_ object that tells Angular how to compile and launch the application.
|
||||
`@NgModule` takes a metadata object that tells Angular how to compile and launch the application.
|
||||
|
||||
The `@NgModule` properties for the minimal `AppModule` generated by the CLI are as follows:
|
||||
* **_declarations_**—this application's lone component.
|
||||
* **_imports_**—import `BrowserModule` to have browser specific services such as DOM rendering, sanitization, and location.
|
||||
* **_providers_**—the service providers.
|
||||
* **_bootstrap_**—the _root_ component that Angular creates and inserts
|
||||
into the `index.html` host web page.
|
||||
|
||||
* **[_declarations_](#declarations)** — declares the application components. At the moment, there is only the `AppComponent`.
|
||||
|
||||
|
||||
* **[_imports_](#imports)** — the `BrowserModule`, which this and every application must import in order to run the app in a browser.
|
||||
|
||||
|
||||
* **[_providers_](#providers)** — there are none to start but you are likely to add some soon.
|
||||
|
||||
|
||||
* **[_bootstrap_](#bootstrap-array)** — the _root_ `AppComponent` that Angular creates and inserts into the `index.html` host web page.
|
||||
|
||||
The [Angular Modules (NgModules)](guide/ngmodule) guide dives deeply into the details of `@NgModule`.
|
||||
All you need to know at the moment is a few basics about these four properties.
|
||||
The default CLI application only has one component, `AppComponent`, so it
|
||||
is in both the `declarations` and the `bootstrap` arrays.
|
||||
|
||||
{@a declarations}
|
||||
|
||||
## The `declarations` array
|
||||
|
||||
### The _declarations_ array
|
||||
The module's `declarations` array tells Angular which components belong to that module.
|
||||
As you create more components, add them to `declarations`.
|
||||
|
||||
You tell Angular which components belong to the `AppModule` by listing it in the module's `declarations` array.
|
||||
As you create more components, you'll add them to `declarations`.
|
||||
You must declare every component in exactly one `NgModule` class.
|
||||
If you use a component without declaring it, Angular returns an
|
||||
error message.
|
||||
|
||||
You must declare _every_ component in an Angular Module class.
|
||||
If you use a component without declaring it, you'll see a clear error message in the browser console.
|
||||
The `declarations` array only takes declarables. Declarables
|
||||
are components, [directives](guide/attribute-directives) and [pipes](guide/pipes).
|
||||
All of a module's declarables must be in the `declarations` array.
|
||||
Declarables must belong to exactly one module. The compiler emits
|
||||
an error if you try to declare the same class in more than one module.
|
||||
|
||||
You'll learn to create two other kinds of classes —
|
||||
[directives](guide/attribute-directives) and [pipes](guide/pipes) —
|
||||
that you must also add to the `declarations` array.
|
||||
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.
|
||||
|
||||
An example of what goes into a declarations array follows:
|
||||
|
||||
```javascript
|
||||
declarations: [
|
||||
YourComponent,
|
||||
YourPipe,
|
||||
YourDirective
|
||||
],
|
||||
```
|
||||
|
||||
A declarable can only belong to one module, so only declare it in
|
||||
one `@NgModule`. When you need it elsewhere,
|
||||
import the module that has the declarable you need in it.
|
||||
|
||||
**Only `@NgModule` references** go in the `imports` array.
|
||||
|
||||
|
||||
### Using directives with `@NgModule`
|
||||
|
||||
Use the `declarations` array for directives.
|
||||
To use a directive, component, or pipe in a module, you must do a few things:
|
||||
|
||||
1. Export it from the file where you wrote it.
|
||||
2. Import it into the appropriate module.
|
||||
3. Declare it in the `@NgModule` `declarations` array.
|
||||
|
||||
|
||||
Those three steps look like the following. In the file where you create your directive, export it.
|
||||
The following example, named `ItemDirective` is the default directive structure that the CLI generates in its own file, `item.directive.ts`:
|
||||
|
||||
<code-example path="bootstrapping/src/app/item.directive.ts" region="directive" title="src/app/item.directive.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
The key point here is that you have to export it so you can import it elsewhere. Next, import it
|
||||
into the NgModule, in this example `app.module.ts`, with a JavaScript import statement:
|
||||
|
||||
<code-example path="bootstrapping/src/app/app.module.ts" region="directive-import" title="src/app/app.module.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
And in the same file, add it to the `@NgModule` `declarations` array:
|
||||
|
||||
<code-example path="bootstrapping/src/app/app.module.ts" region="declarations" title="src/app/app.module.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
|
||||
Now you could use your `ItemDirective` in a component. This example uses `AppModule`, but you'd do it the same way for a feature module. For more about directives, see [Attribute Directives](guide/attribute-directives) and [Structural Directives](guide/structural-directives). You'd also use the same technique for [pipes](guide/pipes) and components.
|
||||
|
||||
Remember, components, directives, and pipes belong to one module only. You only need to declare them once in your app because you share them by importing the necessary modules. This saves you time and helps keep your app lean.
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
**Only _declarables_** — _components_, _directives_ and _pipes_ — belong in the `declarations` array.
|
||||
Do not put any other kind of class in `declarations`. Do _not_ declare `NgModule` classes. Do _not_ declare service classes. Do _not_ declare model classes.
|
||||
|
||||
</div>
|
||||
|
||||
{@a imports}
|
||||
|
||||
### The _imports_ array
|
||||
## The `imports` array
|
||||
|
||||
Angular Modules are a way to consolidate features that belong together into discrete units.
|
||||
Many features of Angular itself are organized as Angular Modules.
|
||||
HTTP services are in the `HttpClientModule`. The router is in the `RouterModule`.
|
||||
Eventually you may create your own modules.
|
||||
The module's `imports` array appears exclusively in the `@NgModule` metadata object.
|
||||
It tells Angular about other NgModules that this particular module needs to function properly.
|
||||
|
||||
Add a module to the `imports` array when the application requires its features.
|
||||
|
||||
_This_ application, like most applications, executes in a browser.
|
||||
Every application that executes in a browser needs the `BrowserModule` from `@angular/platform-browser`.
|
||||
So every such application includes the `BrowserModule` in its _root_ `AppModule`'s `imports` array.
|
||||
Other guide pages will tell you when you need to add additional modules to this array.
|
||||
|
||||
<div class="alert is-important">
|
||||
|
||||
**Only `@NgModule` classes** go in the `imports` array. Do not put any other kind of class in `imports`.
|
||||
</div>
|
||||
|
||||
<div class="l-sub-section">
|
||||
|
||||
The `import` statements at the top of the file and the NgModule's `imports` array
|
||||
are unrelated and have completely different jobs.
|
||||
|
||||
The _JavaScript_ `import` statements give you access to symbols _exported_ by other files
|
||||
so you can reference them within _this_ file.
|
||||
You add `import` statements to almost every application file.
|
||||
They have nothing to do with Angular and Angular knows nothing about them.
|
||||
|
||||
The _module's_ `imports` array appears _exclusively_ in the `@NgModule` metadata object.
|
||||
It tells Angular about specific _other_ Angular Modules—all of them classes decorated
|
||||
with `@NgModule`—that the application needs to function properly.
|
||||
|
||||
</div>
|
||||
|
||||
{@a providers}
|
||||
|
||||
### The _providers_ array
|
||||
|
||||
Angular apps rely on [_dependency injection (DI)_](guide/dependency-injection)
|
||||
to deliver services to various parts of the application.
|
||||
|
||||
Before DI can inject a service, it must create that service with the help of a _provider_.
|
||||
You can tell DI about a service's _provider_ in a number of ways.
|
||||
Among the most popular ways is to register the service in the root `ngModule.providers` array, which will make that service available _everywhere_.
|
||||
|
||||
For example, a data service provided in the `AppModule`s _providers_ can be injected into any
|
||||
component anywhere in the application.
|
||||
This list of modules are those that export components, directives, or pipes
|
||||
that the component templates in this module reference. In this case, the component is
|
||||
`AppComponent`, which references components, directives, or pipes in `BrowserModule`,
|
||||
`FormsModule`, or `HttpModule`.
|
||||
A component template can reference another component, directive,
|
||||
or pipe when the referenced class is declared in this module or
|
||||
the class was imported from another module.
|
||||
|
||||
You don't have any services to provide yet.
|
||||
But you will create some before long and you may chose to provide many of them here.
|
||||
|
||||
{@a bootstrap-array}
|
||||
|
||||
### The _bootstrap_ array
|
||||
## The `providers` array
|
||||
|
||||
You launch the application by [_bootstrapping_](#main) the root `AppModule`.
|
||||
Among other things, the _bootstrapping_ process creates the component(s) listed in the `bootstrap` array
|
||||
The providers array is where you list the services the app needs. When
|
||||
you list services here, they are available app-wide. You can scope
|
||||
them when using feature modules and lazy loading. For more information, see
|
||||
[Providers](guide/providers).
|
||||
|
||||
## The `bootstrap` array
|
||||
|
||||
The application launches by bootstrapping the root `AppModule`, which is
|
||||
also referred to as an `entryComponent`.
|
||||
Among other things, the bootstrapping process creates the component(s) listed in the `bootstrap` array
|
||||
and inserts each one into the browser DOM.
|
||||
|
||||
Each bootstrapped component is the base of its own tree of components.
|
||||
Inserting a bootstrapped component usually triggers a cascade of component creations that fill out that tree.
|
||||
Inserting a bootstrapped component usually triggers a cascade of
|
||||
component creations that fill out that tree.
|
||||
|
||||
While you can put more than one component tree on a host web page, that's not typical.
|
||||
Most applications have only one component tree and they bootstrap a single _root_ component.
|
||||
While you can put more than one component tree on a host web page,
|
||||
most applications have only one component tree and bootstrap a single root component.
|
||||
|
||||
You can call the one _root_ component anything you want but most developers call it `AppComponent`.
|
||||
This one root component is usually called `AppComponent` and is in the
|
||||
root module's `bootstrap` array.
|
||||
|
||||
Which brings us to the _bootstrapping_ process itself.
|
||||
|
||||
{@a main}
|
||||
|
||||
## Bootstrap in _main.ts_
|
||||
|
||||
While there are many ways to bootstrap an application, most applications do so in the `src/main.ts` that is generated by the Angular CLI.
|
||||
|
||||
<code-example path="cli-quickstart/src/main.ts" title="src/main.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
This code creates a browser platform for dynamic compilation and
|
||||
bootstraps the `AppModule` described above.
|
||||
|
||||
The _bootstrapping_ process sets up the execution environment,
|
||||
digs the _root_ `AppComponent` out of the module's `bootstrap` array,
|
||||
creates an instance of the component and inserts it within the element tag identified by the component's `selector`.
|
||||
|
||||
The `AppComponent` selector — here and in most documentation samples — is `app-root`
|
||||
so Angular looks for a `<app-root>` tag in the `index.html` like this one ...
|
||||
|
||||
<code-example title="src/index.html (body)" linenums="false">
|
||||
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
|
||||
</code-example>
|
||||
|
||||
... and displays the `AppComponent` there.
|
||||
|
||||
The `main.ts` file is very stable. Once you've set it up, you may never change it again.
|
||||
|
||||
## More about Angular Modules
|
||||
|
||||
Your initial app has only a single module, the _root_ module.
|
||||
As your app grows, you'll consider subdividing it into multiple "feature" modules,
|
||||
some of which can be loaded later ("lazy loaded") if and when the user chooses
|
||||
to visit those features.
|
||||
For more on NgModules you're likely to see frequently in apps,
|
||||
see [Frequently Used Modules](#).
|
||||
|
||||
When you're ready to explore these possibilities, visit the [Angular Modules](guide/ngmodule) guide.
|
||||
|
@ -181,7 +181,7 @@ The _Routing Module_ replaces the previous _routing object_ involving the `Modul
|
||||
|
||||
All guided samples with routing use the _Routing Module_ and prose content has been updated,
|
||||
most conspicuously in the
|
||||
[NgModule](guide/ngmodule) guide and [NgModule FAQ](guide/ngmodule-faq) guide.
|
||||
[NgModule](guide/ngmodules) guide and [NgModule FAQ](guide/ngmodule-faq) guide.
|
||||
|
||||
## New "Internationalization" guide (2016-09-30)
|
||||
|
||||
|
@ -160,7 +160,7 @@ Providing the `UserService` with an Angular module is a good choice.
|
||||
<div class="l-sub-section">
|
||||
|
||||
To be precise, Angular module providers are registered with the root injector
|
||||
_unless the module is_ [lazy loaded](guide/ngmodule#lazy-load-DI).
|
||||
_unless the module is_ [lazy loaded](guide/lazy-loading-ngmodules).
|
||||
In this sample, all modules are _eagerly loaded_ when the application starts,
|
||||
so all module providers are registered with the app's root injector.
|
||||
|
||||
|
116
aio/content/guide/entry-components.md
Normal file
116
aio/content/guide/entry-components.md
Normal file
@ -0,0 +1,116 @@
|
||||
# Entry Components
|
||||
|
||||
#### Prerequisites:
|
||||
|
||||
A basic understanding of the following concepts:
|
||||
* [Bootstrapping](guide/bootstrapping).
|
||||
|
||||
<hr />
|
||||
|
||||
An entry component is any component that Angular loads imperatively, (which means you’re not referencing it in the template), by type. You specify an entry component by bootstrapping it in an NgModule,or including it in a routing definition.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
To contrast the two types of components, there are components which are included in the template, which are declarative. Additionally, there are components which you load imperatively; that is, entry components.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
There are two main kinds of entry components:
|
||||
|
||||
* The bootstrapped root component.
|
||||
* A component you specify in a route definition.
|
||||
|
||||
|
||||
## A bootstrapped entry component
|
||||
|
||||
|
||||
The following is an example of specifying a bootstrapped component,
|
||||
`AppComponent`, in a basic `app.module.ts`:
|
||||
|
||||
```javascript
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule,
|
||||
AppRoutingModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent] // bootstrapped entry component
|
||||
})
|
||||
```
|
||||
A bootstrapped component is an entry component
|
||||
that Angular loads into the DOM during the bootstrap (application launch), process.
|
||||
Other entry components are loaded dynamically by other means, such as with the router.
|
||||
|
||||
Angular loads a root `AppComponent` dynamically because it's listed by type in `@NgModule.bootstrap`.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
A component can also be bootstrapped imperatively with the module's `ngDoBootstrap()` method.
|
||||
The `@NgModule.bootstrap` property tells the compiler that this is an entry component and
|
||||
it should generate code to bootstrap the application with this component.
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
A bootstrapped component is necessarily an entry component because bootstrapping is an imperative process, thus it needs to have an entry component.
|
||||
|
||||
## A routed entry component
|
||||
|
||||
|
||||
The second kind of entry component occurs in a route definition like
|
||||
this:
|
||||
|
||||
```javascript
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: CustomerListComponent
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
A route definition refers to a component by its type with `component: CustomerListComponent`.
|
||||
|
||||
All router components must be `entryComponents`. Because this would require you to add the component in two places (router and `entryComponent`) the Compiler is smart enough to recognize that this is a router definition and automatically add the router component into `entryComponents`.
|
||||
|
||||
|
||||
## The `entryComponents` array
|
||||
|
||||
Though the `@NgModule` decorator has an `entryComponents` array, most of the time
|
||||
you won't have to explicitly set any entry components because Angular adds components listed in `@NgModule.bootstrap` and those in route definitions to entry components automatically. Though these two mechanisms account for most entry components, if your app happens to bootstrap or dynamically load a component by type imperatively,
|
||||
you must add it to `entryComponents` explicitly.
|
||||
|
||||
### `entryComponents` and the compiler
|
||||
|
||||
For production apps you want to load the smallest code possible.
|
||||
The code should contain only the classes that you actually need and
|
||||
exclude components that are never used. For this reason, the Angular compiler only generates code for components which are reachable from the `entryComponents`; This means that adding more references to `@NgModule.declarations` does not imply that they will necessarily be included in the final bundle.
|
||||
|
||||
In fact, many libraries declare and export components you'll never use.
|
||||
For example, a material design library will export all components because it doesn’t know which ones the you will use. However, it is unlikely that the you will use them all.
|
||||
For the ones you don't reference, the tree shaker drops these components from the final code package.
|
||||
|
||||
If a component isn't an _entry component_ or isn't found in a template,
|
||||
The tree shaker will throw it away. So, it's best to add only the components that are truly entry components to help keep your app
|
||||
as trim as possible.
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
## More on Angular modules
|
||||
|
||||
You may also be interested in the following:
|
||||
* [Types of NgModules](guide/module-types)
|
||||
* [Lazy Loading Modules with the Angular Router](guide/lazy-loading-ngmodules).
|
||||
* [Providers](guide/providers).
|
||||
* [NgModules FAQ](guide/ngmodule-faq).
|
||||
|
||||
|
||||
|
||||
|
134
aio/content/guide/feature-modules.md
Normal file
134
aio/content/guide/feature-modules.md
Normal file
@ -0,0 +1,134 @@
|
||||
# Feature Modules
|
||||
|
||||
Feature modules are NgModules for the purpose of organizing code.
|
||||
|
||||
#### Prerequisites
|
||||
A basic understanding of the following:
|
||||
* [Bootstrapping](guide/bootstrapping).
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
* [Frequently Used Modules](guide/frequent-ngmodules).
|
||||
|
||||
For the final sample app with a feature module that this page describes,
|
||||
see the <live-example></live-example>.
|
||||
|
||||
<hr>
|
||||
|
||||
As your app grows, you can organize code relevant for a specific feature.
|
||||
This helps apply clear boundaries for features. With feature modules,
|
||||
you can keep code related to a specific functionality or feature
|
||||
separate from other code. Delineating areas of your
|
||||
app helps with collaboration between developers and teams, separating
|
||||
directives, and managing the size of the root module.
|
||||
|
||||
|
||||
## Feature modules vs. root modules
|
||||
|
||||
A feature module is an organizational best practice, as opposed to a concept of the core Angular API. A feature module delivers a cohesive set of functionality focused on a
|
||||
specific application need such as a user workflow, routing, or forms.
|
||||
While you can do everything within the root module, feature modules
|
||||
help you partition the app into focused areas. A feature module
|
||||
collaborates with the root module and with other modules through
|
||||
the services it provides and the components, directives, and
|
||||
pipes that it shares.
|
||||
|
||||
## How to make a feature module
|
||||
|
||||
Assuming you already have a CLI generated app, create a feature
|
||||
module using the CLI by entering the following command in the
|
||||
root project directory. Replace `CustomerDashboard` with the
|
||||
name of your module. You can omit the word module because the CLI appends it:
|
||||
|
||||
```sh
|
||||
ng generate module CustomerDashboard
|
||||
|
||||
```
|
||||
|
||||
|
||||
This causes the CLI to create a folder called `customer-dashboard` with a file inside called `customer-dashboard.module.ts` with the following contents:
|
||||
|
||||
```ts
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule
|
||||
],
|
||||
declarations: []
|
||||
})
|
||||
|
||||
export class CustomerDashboardModule { }
|
||||
|
||||
|
||||
```
|
||||
|
||||
The structure of an NgModule is the same whether it is a root module or a feature module. In the CLI generated feature module, there are two JavaScript import statements at the top of the file: the first imports `NgModule`, which, like the root module, lets you use the `@NgModule` decorator; the second imports `CommonModule`, which contributes many common directives such as `ngIf` and `ngFor`. Feature modules import `CommonModule` instead of `BrowserModule`, which is only imported once in the root module. `CommonModule` only contains information for common directives such as `ngIf` and `ngFor` which are needed in most templates, whereas `BrowserModule` configures the Angular app for the browser which needs to be done only once.
|
||||
|
||||
The `declarations` array is available for you to add declarables, which
|
||||
are components, directives, and pipes that belong exclusively to this particular module. To add a component, enter the following command at the command line where `customer-dashboard` is the directory where the CLI generated the feature module and `CustomerDashboard` is the name of the component:
|
||||
|
||||
```sh
|
||||
ng generate component customer-dashboard/CustomerDashboard
|
||||
|
||||
```
|
||||
|
||||
This generates a folder for the new component within the customer-dashboard folder and updates the feature module with the `CustomerDashboardComponent` info:
|
||||
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard.module.ts" region="customer-dashboard-component" title="src/app/customer-dashboard.module.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
|
||||
|
||||
The `CustomerDashboardComponent` is now in the JavaScript import list at the top and added to the `declarations` array, which lets Angular know to associate this new component with this feature module.
|
||||
|
||||
## Importing a feature module
|
||||
|
||||
To incorporate the feature module into your app, you have to let the root module, `app.module.ts`, know about it. Notice the `CustomerDashboardModule` export at the bottom of `customer-dashboard.module.ts`. This exposes it so that other modules can get to it. To import it into the AppModule, add it to the imports in `app.module.ts` and to the imports array:
|
||||
|
||||
<code-example path="feature-modules/src/app/app.module.ts" region="app-module" title="src/app/app.module.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
|
||||
Now the `AppModule` knows about the feature module. If you were to add any service providers to the feature module, `AppModule` would know about those too, as would any other feature modules. However, NgModules don’t expose their components.
|
||||
|
||||
|
||||
## Rendering a feature module’s component template
|
||||
|
||||
When the CLI generated the `CustomerDashboardComponent` for the feature module, it included a template, `customer-dashboard.component.html`, with the following markup:
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard/customer-dashboard.component.html" region="feature-template" title="src/app/customer-dashboard/customer-dashboard/customer-dashboard.component.html" linenums="false">
|
||||
</code-example>
|
||||
|
||||
|
||||
To see this HTML in the `AppComponent`, you first have to export the `CustomerDashboardComponent` in the `CustomerDashboardModule`. In `customer-dashboard.module.ts`, just beneath the declarations array, add an exports array containing `CustomerDashboardModule`:
|
||||
|
||||
<code-example path="feature-modules/src/app/customer-dashboard/customer-dashboard.module.ts" region="customer-dashboard-component" title="src/app/customer-dashboard.module.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
|
||||
|
||||
Next, in the `AppComponent`, `app.component.html`, add the tag `<app-customer-dashboard>`:
|
||||
|
||||
<code-example path="feature-modules/src/app/app.component.html" region="app-component-template" title="src/app/app.component.html" linenums="false">
|
||||
</code-example>
|
||||
|
||||
|
||||
Now, in addition to the title that renders by default, the `CustomerDashboardComponent` template renders too:
|
||||
|
||||
|
||||
<figure>
|
||||
<img src="generated/images/guide/feature-modules/feature-module.png" alt="feature module component">
|
||||
</figure>
|
||||
|
||||
<hr />
|
||||
|
||||
## More on NgModules
|
||||
|
||||
You may also be interested in the following:
|
||||
* [Lazy Loading Modules with the Angular Router](guide/lazy-loading-ngmodules).
|
||||
* [Providers](guide/providers).
|
||||
* [Types of NgModules](guide/module-types).
|
||||
|
||||
|
138
aio/content/guide/frequent-ngmodules.md
Normal file
138
aio/content/guide/frequent-ngmodules.md
Normal file
@ -0,0 +1,138 @@
|
||||
# Frequently Used Modules
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
A basic understanding of [Bootstrapping](guide/bootstrapping).
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
An Angular app needs at least one module that serves as the root module.
|
||||
As you add features to your app, you can add them in modules.
|
||||
The following are frequently used Angular modules with examples
|
||||
of some of the things they contain:
|
||||
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<th style="vertical-align: top">
|
||||
NgModule
|
||||
</th>
|
||||
|
||||
<th style="vertical-align: top">
|
||||
Import it from
|
||||
</th>
|
||||
|
||||
<th style="vertical-align: top">
|
||||
Why you use it
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>BrowserModule</code></td>
|
||||
<td><code>@angular/platform-browser</code></td>
|
||||
<td>When you want to run your app in a browser</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>CommonModule</code></td>
|
||||
<td><code>@angular/common</code></td>
|
||||
<td>When you want to use <code>NgIf</code>, <code>NgFor</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>FormsModule</code></td>
|
||||
<td><code>@angular/forms</code></td>
|
||||
<td>When you build template driven forms (includes <code>NgModel</code>)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>ReactiveFormsModule</code></td>
|
||||
<td><code>@angular/forms</code></td>
|
||||
<td>When building reactive forms</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>RouterModule</code></td>
|
||||
<td><code>@angular/forms</code></td>
|
||||
<td>For Routing and when you want to use <code>RouterLink</code>,<code>.forRoot()</code>, and <code>.forChild()</code></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><code>HttpModule</code></td>
|
||||
<td><code>@angular/http</code></td>
|
||||
<td>When you to talk to a server</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
## Importing modules
|
||||
|
||||
When you use these Angular modules, import them in `AppModule`,
|
||||
or your feature module as appropriate, and list them in the `@NgModule`
|
||||
`imports` array. For example, in the basic app generated by the CLI,
|
||||
`BrowserModule` is the first import at the top of the `AppModule`,
|
||||
`app.module.ts`. Notice that this is the same case for `FormsModule` and `HttpModule`.
|
||||
|
||||
|
||||
```javascript
|
||||
/* import modules so that AppModule can access them */
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [ /* add modules here so Angular knows to use them */
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
```
|
||||
|
||||
The imports at the top of the array are JavaScript import statements
|
||||
while the `imports` array within `@NgModule` is Angular specific.
|
||||
For more information on the difference, see [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
|
||||
|
||||
## `BrowserModule` and `CommonModule`
|
||||
|
||||
`BrowserModule` imports `CommonModule`, which contributes many common
|
||||
directives such as `ngIf` and `ngFor`. Additionally, `BrowserModule`
|
||||
re-exports `CommonModule` making all of its directives available
|
||||
to any module that imports `BrowserModule`.
|
||||
|
||||
For apps that run in the browser, import `BrowserModule` in the
|
||||
root `AppModule` because it provides services that are essential
|
||||
to launch and run a browser app. `BrowserModule`’s providers
|
||||
are for the whole app so it should only be in the root module,
|
||||
not in feature modules. Feature modules only need the common
|
||||
directives in `CommonModule`; they don’t need to re-install app-wide providers.
|
||||
|
||||
If you do import `BrowserModule` into a lazy loaded feature module,
|
||||
Angular returns an error telling you to use `CommonModule` instead.
|
||||
|
||||
<figure>
|
||||
<img src="generated/images/guide/frequent-ngmodules/browser-module-error.gif" width=750 alt="BrowserModule error">
|
||||
</figure>
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
## More on NgModules
|
||||
|
||||
You may also be interested in the following:
|
||||
* [Bootstrapping](guide/bootstrapping).
|
||||
* [NgModules](guide/ngmodules).
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
|
@ -478,9 +478,11 @@ Read more in the [Lifecycle Hooks](guide/lifecycle-hooks) page.
|
||||
Angular has the following types of modules:
|
||||
|
||||
* [NgModules](guide/glossary#ngmodule).
|
||||
For details and examples, see the [NgModules](guide/ngmodule) page.
|
||||
For details and examples, see the [NgModules](guide/ngmodules) page.
|
||||
* ES2015 modules, as described in this section.
|
||||
|
||||
For a comparison, see [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
@ -526,7 +528,8 @@ An NgModule identifies the components, directives, and pipes that the applicatio
|
||||
Every Angular application has an application root-module class. By convention, the class is
|
||||
called `AppModule` and resides in a file named `app.module.ts`.
|
||||
|
||||
For details and examples, see [NgModules](guide/ngmodule).
|
||||
For details and examples, see [NgModules](guide/ngmodules) and the
|
||||
related files in that section.
|
||||
|
||||
|
||||
</div>
|
||||
|
230
aio/content/guide/lazy-loading-ngmodules.md
Normal file
230
aio/content/guide/lazy-loading-ngmodules.md
Normal file
@ -0,0 +1,230 @@
|
||||
# Lazy Loading Feature Modules
|
||||
|
||||
#### Prerequisites
|
||||
A basic understanding of the following:
|
||||
* [Feature Modules](guide/feature-modules).
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
* [Frequently Used Modules](guide/frequent-ngmodules).
|
||||
* [Types of Modules](guide/module-types).
|
||||
* [Routing and Navigation](guide/router).
|
||||
|
||||
For the final sample app with two lazy loaded modules that this page describes, see the <live-example></live-example>.
|
||||
|
||||
<hr>
|
||||
|
||||
## High level view
|
||||
|
||||
There are three main steps to setting up a lazy loaded feature module:
|
||||
|
||||
1. Create the feature module.
|
||||
1. Create the feature module’s routing module.
|
||||
1. Configure the routes.
|
||||
|
||||
## Set up an app
|
||||
|
||||
If you don’t already have an app, you can follow the steps below to
|
||||
create one with the CLI. If you do already have an app, skip to
|
||||
[Configure the routes](#config-routes). Enter the following command
|
||||
where `customer-app` is the name of your app:
|
||||
|
||||
```sh
|
||||
ng new customer-app --routing
|
||||
```
|
||||
|
||||
This creates an app called `customer-app` and the `--routing` flag
|
||||
generates a file called `app-routing.module.ts`, which is one of
|
||||
the files you need for setting up lazy loading for your feature module.
|
||||
Navigate into the project by issuing the command `cd customer-app`.
|
||||
|
||||
## Create a feature module with routing
|
||||
|
||||
Next, you’ll need a feature module to route to. To make one, enter
|
||||
the following command at the terminal window prompt where `customers` is the name of the module:
|
||||
|
||||
```sh
|
||||
ng generate module customers --routing
|
||||
```
|
||||
|
||||
This creates a customers folder with two files inside; `CustomersModule`
|
||||
and `CustomersRoutingModule`. `CustomersModule` will act as the gatekeeper
|
||||
for anything that concerns customers. `CustomersRoutingModule` will handle
|
||||
any customer-related routing. This keeps the app’s structure organized as
|
||||
the app grows and allows you to reuse this module while easily keeping its routing intact.
|
||||
|
||||
The CLI imports the `CustomersRoutingModule` into the `CustomersModule` by
|
||||
adding a JavaScript import statement at the top of the file and adding
|
||||
`CustomersRoutingModule` to the `@NgModule` `imports` array.
|
||||
|
||||
## Add a component to the feature module
|
||||
|
||||
In order to see the module being lazy loaded in the browser, create a component to render some HTML when the app loads `CustomersModule`. At the command line, enter the following:
|
||||
|
||||
```sh
|
||||
ng generate component customers/customer-list
|
||||
```
|
||||
|
||||
This creates a folder inside of `customers` called `customer-list`
|
||||
with the four files that make up the component.
|
||||
|
||||
<!-- For more information
|
||||
about components, see [Components](). -->
|
||||
|
||||
Just like with the routing module, the CLI imports the
|
||||
`CustomerListComponent` into the `CustomersModule`.
|
||||
|
||||
|
||||
## Add another feature module
|
||||
|
||||
For another place to route to, create a second feature module with routing:
|
||||
|
||||
```sh
|
||||
ng generate module orders --routing
|
||||
```
|
||||
|
||||
This makes a new folder called `orders` containing an `OrdersModule` and an `OrdersRoutingModule`.
|
||||
|
||||
Now, just like with the `CustomersModule`, give it some content:
|
||||
|
||||
```sh
|
||||
ng generate component orders/order-list
|
||||
```
|
||||
|
||||
## Set up the UI
|
||||
|
||||
Though you can type the URL into the address bar, a nav
|
||||
is easier for the user and more common. Replace the default
|
||||
placeholder markup in `app.component.html` with a custom nav
|
||||
so you can easily navigate to your modules in the browser:
|
||||
|
||||
|
||||
<code-example path="lazy-loading/src/app/app.component.html" region="app-component-template" title="src/app/app.component.html" linenums="false">
|
||||
|
||||
</code-example>
|
||||
|
||||
|
||||
|
||||
To see your app in the browser so far, enter the following command in the terminal window:
|
||||
|
||||
```sh
|
||||
ng serve
|
||||
```
|
||||
|
||||
Then go to `localhost:4200` where you should see “app works!” and three buttons.
|
||||
|
||||
<figure>
|
||||
<img src="generated/images/guide/lazy-loading-ngmodules/three-buttons.png" width="300" alt="three buttons in the browser">
|
||||
</figure>
|
||||
|
||||
|
||||
To make the buttons work, you need to configure the routing modules.
|
||||
|
||||
{@a config-routes}
|
||||
|
||||
## Configure the routes
|
||||
|
||||
The two feature modules, `OrdersModule` and `CustomersModule`, have to be
|
||||
wired up to the `AppRoutingModule` so the router knows about them. The structure is as follows:
|
||||
|
||||
<figure>
|
||||
<img src="generated/images/guide/lazy-loading-ngmodules/lazy-load-relationship.jpg" width="400" alt="lazy loaded modules diagram">
|
||||
</figure>
|
||||
|
||||
|
||||
Each feature module acts as a doorway via the router. In the `AppRoutingModule`, you configure the routes to the feature modules, in this case `OrdersModule` and `CustomersModule`. This way, the router knows to go to the feature module. The feature module then connects the `AppRoutingModule` to the `CustomersRoutingModule` or the `OrdersRoutingModule`. Those routing modules tell the router where to go to load relevant components.
|
||||
|
||||
### Routes at the app level
|
||||
|
||||
In `AppRoutingModule`, update the `routes` array with the following:
|
||||
|
||||
|
||||
<code-example path="lazy-loading/src/app/app-routing.module.ts" region="const-routes" title="src/app/app-routing.module.ts" linenums="false">
|
||||
|
||||
</code-example>
|
||||
|
||||
|
||||
The import statements stay the same. The first two paths are the routes to the `CustomersModule` and the `OrdersModule` respectively. Notice that the lazy loading syntax uses `loadChildren` followed by a string that is the path to the module, a hash mark or `#`, and the module’s class name.
|
||||
|
||||
### Inside the feature module
|
||||
|
||||
Next, take a look at `customers.module.ts`. If you’re using the CLI and following the steps outlined in this page, you don’t have to do anything here. The feature module is like a connector between the `AppRoutingModule` and the feature routing module. The `AppRoutingModule` imports the feature module, `CustomersModule`, and `CustomersModule` in turn imports the `CustomersRoutingModule`.
|
||||
|
||||
|
||||
<code-example path="lazy-loading/src/app/customers/customers.module.ts" region="customers-module" title="src/app/customers/customers.module.ts" linenums="false">
|
||||
|
||||
</code-example>
|
||||
|
||||
|
||||
|
||||
The `customers.module.ts` file imports the `CustomersRoutingModule` and `CustomerListComponent` so the `CustomersModule` class can have access to them. `CustomersRoutingModule` is then listed in the `@NgModule` `imports` array giving `CustomersModule` access to its own routing module, and `CustomerListComponent` is in the `declarations` array, which means `CustomerListComponent` belongs to the `CustomersModule`.
|
||||
|
||||
|
||||
### Configure the feature module’s routes
|
||||
|
||||
The next step is in `customers-routing.module.ts`. First, import the component at the top of the file with the other JavaScript import statements. Then, add the route to `CustomerListComponent`.
|
||||
|
||||
<code-example path="lazy-loading/src/app/customers/customers-routing.module.ts" region="customers-routing-module" title="src/app/customers/customers-routing.module.ts" linenums="false">
|
||||
|
||||
</code-example>
|
||||
|
||||
|
||||
Notice that the `path` is set to an empty string. This is because the path in `AppRoutingModule` is already set to `customers`, so this route in the `CustomersRoutingModule`, is already within the `customers` context. Every route in this routing module is a child route.
|
||||
|
||||
Repeat this last step of importing the `OrdersListComponent` and configuring the Routes array for the `orders-routing.module.ts`:
|
||||
|
||||
<code-example path="lazy-loading/src/app/orders/orders-routing.module.ts" region="orders-routing-module-detail" title="src/app/orders/orders-routing.module.ts (excerpt)" linenums="false">
|
||||
|
||||
</code-example>
|
||||
|
||||
Now, if you view the app in the browser, the three buttons take you to each module.
|
||||
|
||||
## Confirm it’s working
|
||||
|
||||
You can check to see that a module is indeed being lazy loaded with the Chrome developer tools. In Chrome, open the dev tools by pressing `Cmd+Option+i` on a Mac or `Ctrl+Alt+i` on a PC and go to the Network Tab.
|
||||
|
||||
<figure>
|
||||
<img src="generated/images/guide/lazy-loading-ngmodules/network-tab.png" width="600" alt="lazy loaded modules diagram">
|
||||
</figure>
|
||||
|
||||
|
||||
Click on the Orders or Customers button. If you see a chunk appear, you’ve wired everything up properly and the feature module is being lazy loaded. A chunk should appear for Orders and for Customers but will only appear once for each.
|
||||
|
||||
|
||||
<figure>
|
||||
<img src="generated/images/guide/lazy-loading-ngmodules/chunk-arrow.png" width="600" alt="lazy loaded modules diagram">
|
||||
</figure>
|
||||
|
||||
|
||||
To see it again, or to test after working in the project, clear everything out by clicking the circle with a line through it in the upper left of the Network Tab:
|
||||
|
||||
<figure>
|
||||
<img src="generated/images/guide/lazy-loading-ngmodules/clear.gif" width="200" alt="lazy loaded modules diagram">
|
||||
</figure>
|
||||
|
||||
|
||||
Then reload with `Cmd+r` or `Ctrl+r`, depending on your platform.
|
||||
|
||||
## `forRoot()` and `forChild()`
|
||||
|
||||
You might have noticed that the CLI adds `RouterModule.forRoot(routes)` to the `app-routing.module.ts` `imports` array. This lets Angular know that this module,
|
||||
`AppRoutingModule`, is a routing module and `forRoot()` specifies that this is the root
|
||||
routing module. It configures all the
|
||||
routes you pass to it, gives you access to the router directives, and registers the `RouterService`.
|
||||
Use `forRoot()` in the `AppRoutingModule`—that is, one time in the app at the root level.
|
||||
|
||||
The CLI also adds `RouterModule.forChild(routes)` to feature routing modules. This way, Angular
|
||||
knows that the route list is only responsible for providing additional routes and is intended for feature modules. You can use `forChild()` in multiple modules.
|
||||
|
||||
`forRoot()` contains injector configuration which is global; such as configuring the Router. `forChild()` has no injector configuration, only directives such as `RouterOutlet` and `RouterLink`.
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
## More on NgModules and routing
|
||||
|
||||
You may also be interested in the following:
|
||||
* [Routing and Navigation](guide/router).
|
||||
* [Providers](guide/providers).
|
||||
* [Types of NgModules](guide/module-types).
|
||||
|
||||
|
||||
|
192
aio/content/guide/module-types.md
Normal file
192
aio/content/guide/module-types.md
Normal file
@ -0,0 +1,192 @@
|
||||
|
||||
|
||||
# Types of Feature Modules
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
A basic understanding of the following concepts:
|
||||
* [Feature Modules](guide/feature-modules).
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
* [Frequently Used Modules](guide/frequent-ngmodules).
|
||||
|
||||
<hr>
|
||||
|
||||
There are five general categories of feature modules which
|
||||
tend to fall into the following groups:
|
||||
|
||||
* Domain feature modules.
|
||||
* Routed feature modules.
|
||||
* Routing modules.
|
||||
* Service feature modules.
|
||||
* Widget feature modules.
|
||||
|
||||
While the following guidelines describe the use of each type and their
|
||||
typical characteristics, in real world apps, you may see hybrids.
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
<th style="vertical-align: top">
|
||||
Feature Module
|
||||
</th>
|
||||
|
||||
<th style="vertical-align: top">
|
||||
Guidelines
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Domain</td>
|
||||
<td>
|
||||
Domain feature modules deliver a user experience dedicated to a particular application domain like editing a customer or placing an order.
|
||||
|
||||
They typically have a top component that acts as the feature root and private, supporting sub-components descend from it.
|
||||
|
||||
Domain feature modules consist mostly of declarations. Only the top component is exported.
|
||||
|
||||
Domain feature modules rarely have providers. When they do, the lifetime of the provided services should be the same as the lifetime of the module.
|
||||
|
||||
Domain feature modules are typically imported exactly once by a larger feature module.
|
||||
|
||||
They might be imported by the root `AppModule` of a small application that lacks routing.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Routed</td>
|
||||
<td>
|
||||
Routed feature modules are domain feature modules whose top components are the targets of router navigation routes.
|
||||
|
||||
All lazy-loaded modules are routed feature modules by definition.
|
||||
|
||||
Routed feature modules don’t export anything 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. Doing so would trigger an eager load, defeating the purpose of lazy loading.That means you won’t see them mentioned among the `AppModule` imports. An eager loaded routed feature module must be imported by another module so that the compiler learns about its components.
|
||||
|
||||
Routed feature modules rarely have providers for reasons explained in Lazy Loading Feature Modules(page forthcoming). When they do, the lifetime of the provided services should be the same as the lifetime of the module. Don't provide application-wide singleton services in a routed feature module or in a module that the routed module imports.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Routing</td>
|
||||
<td>
|
||||
|
||||
A routing module provides routing configuration for another module and separates routing concerns from its companion module.
|
||||
|
||||
A routing module typically does the following:
|
||||
|
||||
<ul>
|
||||
<li>Defines routes.</li>
|
||||
<li>Adds router configuration to the module's imports.</li>
|
||||
<li>Adds guard and resolver service providers to the module's providers.</li>
|
||||
<li>The name of the routing module should parallel the name of its companion module, using the suffix "Routing". For example, <code>FooModule</code> in <code>foo.module.ts</code> has a routing module named <code>FooRoutingModule</code> in <code>foo-routing.module.ts</code>. If the companion module is the root <code>AppModule</code>, the <code>AppRoutingModule</code> adds router configuration to its imports with <code>RouterModule.forRoot(routes)</code>. All other routing modules are children that import <code>RouterModule.forChild(routes)</code>.</li>
|
||||
<li>A routing module re-exports the <code>RouterModule</code> as a convenience so that components of the companion module have access to router directives such as <code>RouterLink</code> and <code>RouterOutlet</code>.</li>
|
||||
<li>A routing module does not have its own declarations. Components, directives, and pipes are the responsibility of the feature module, not the routing module.</li>
|
||||
</ul>
|
||||
|
||||
A routing module should only be imported by its companion module.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Service</td>
|
||||
<td>
|
||||
|
||||
Service modules provide utility services such as data access and messaging. Ideally, they consist entirely of providers and have no declarations. Angular's `HttpModule` is a good example of a service module.
|
||||
|
||||
The root `AppModule` is the only module that should import service modules.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Widget</td>
|
||||
<td>
|
||||
|
||||
A widget module makes components, directives, and pipes available to external modules. Many third-party UI component libraries are widget modules.
|
||||
|
||||
A widget module should consist entirely of declarations, most of them exported.
|
||||
|
||||
A widget module should rarely have providers.
|
||||
|
||||
Import widget modules in any module whose component templates need the widgets.
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
The following table summarizes the key characteristics of each feature module group.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th style="vertical-align: top">
|
||||
Feature Module
|
||||
</th>
|
||||
|
||||
<th style="vertical-align: top">
|
||||
Declarations
|
||||
</th>
|
||||
|
||||
<th style="vertical-align: top">
|
||||
Providers
|
||||
</th>
|
||||
|
||||
<th style="vertical-align: top">
|
||||
Exports
|
||||
</th>
|
||||
|
||||
<th style="vertical-align: top">
|
||||
Imported by
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Domain</td>
|
||||
<td>Yes</td>
|
||||
<td>Rare</td>
|
||||
<td>Top component</td>
|
||||
<td>Feature, AppModule</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Routed</td>
|
||||
<td>Yes</td>
|
||||
<td>Rare</td>
|
||||
<td>No</td>
|
||||
<td>None</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Routing</td>
|
||||
<td>No</td>
|
||||
<td>Yes (Guards)</td>
|
||||
<td>RouterModule</td>
|
||||
<td>Feature (for routing)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Service</td>
|
||||
<td>No</td>
|
||||
<td>Yes</td>
|
||||
<td>No</td>
|
||||
<td>AppModule</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Widget</td>
|
||||
<td>Yes</td>
|
||||
<td>Rare</td>
|
||||
<td>Yes</td>
|
||||
<td>Feature</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr />
|
||||
|
||||
## More on NgModules
|
||||
|
||||
You may also be interested in the following:
|
||||
* [Lazy Loading Modules with the Angular Router](guide/lazy-loading-ngmodules).
|
||||
* [Providers](guide/providers).
|
||||
* [Types of NgModules](guide/module-types).
|
244
aio/content/guide/ngmodule-api.md
Normal file
244
aio/content/guide/ngmodule-api.md
Normal file
@ -0,0 +1,244 @@
|
||||
# NgModule API
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
A basic understanding of the following concepts:
|
||||
* [Bootstrapping](guide/bootstrapping).
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
|
||||
<hr />
|
||||
|
||||
## Purpose of `@NgModule`
|
||||
|
||||
At a high level, NgModules are a way to organize Angular apps
|
||||
and they accomplish this through the metadata in the `@NgModule`
|
||||
decorator. The metadata falls
|
||||
into three categories:
|
||||
|
||||
* **Static:** Compiler configuration which tells the compiler about directive selectors and where in templates the directives should be applied through selector matching. This is configured via the `declarations` array.
|
||||
* **Runtime:** Injector configuration via the `providers` array.
|
||||
* **Composability/Grouping:** Bringing NgModules together and making them available via the `imports` and `exports` arrays.
|
||||
|
||||
```ts
|
||||
@NgModule({
|
||||
// Static, that is compiler configuration
|
||||
declarations: [], // Configure the selectors
|
||||
entryComponents: [], // Generate the host factory
|
||||
|
||||
// Runtime, or injector configuration
|
||||
providers: [], // Runtime injector configuration
|
||||
|
||||
// Composability / Grouping
|
||||
imports: [], // composing NgModules together
|
||||
exports: [] // making NgModules available to other parts of the app
|
||||
})
|
||||
```
|
||||
|
||||
## `@NgModule` metadata
|
||||
|
||||
The following table summarizes the `NgModule` metadata properties.
|
||||
|
||||
<table>
|
||||
|
||||
<tr>
|
||||
|
||||
<th>
|
||||
Property
|
||||
</th>
|
||||
|
||||
<th>
|
||||
Description
|
||||
</th>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td style="vertical-align: top">
|
||||
<code>declarations</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
|
||||
A list of [declarable](guide/ngmodule-faq#q-declarable) classes,
|
||||
(*components*, *directives*, and *pipes*) that _belong to this module_.
|
||||
|
||||
1) When compiling a template, you need to determine a set of selectors which should be used for triggering their corresponding directives.
|
||||
2) The template is compiled within a context of an `NgModule`—the `NgModule` which this template's component is declared in—which determines the set of selectors using the following rules:
|
||||
a) All selectors of directives listed in `declarations`
|
||||
b) All exported selectors of imported `NgModules`.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Don't re-declare a class imported from another module.
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td style="vertical-align: top">
|
||||
<code>providers</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
|
||||
A list of dependency-injection providers.
|
||||
|
||||
Angular registers these providers with the NgModule's injector.
|
||||
If it is the NgModule used for bootstrapping that it is the root injector.
|
||||
|
||||
These services become available for injection into any component, directive, pipe or service which is a child of this injector.
|
||||
|
||||
A lazy-loaded module has its own injector which
|
||||
is typically a 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 `UserService`,
|
||||
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 provided by their injectors.
|
||||
|
||||
For more information on injector hierarchy and scoping, see [Providers](guide/providers).
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td style="vertical-align: top">
|
||||
<code>imports</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
|
||||
A list of modules which should be folded into this module. Folded means it is
|
||||
as if all of the imported NgModule properties were declared here.
|
||||
|
||||
Specifically, it is as if the list of modules whose exported components, directives, or pipes
|
||||
are referenced by the component templates were declared in this module.
|
||||
|
||||
A component template can [reference](guide/ngmodule-faq#q-template-reference) another component, directive, or pipe
|
||||
when the reference is declared in this module
|
||||
or if the imported module has exported it.
|
||||
For example, a component can use the `NgIf` and `NgFor` directives only if the
|
||||
module has imported the Angular `CommonModule` (perhaps indirectly by importing `BrowserModule`).
|
||||
|
||||
You can import many standard directives from the `CommonModule`
|
||||
but some familiar directives belong to other modules.
|
||||
For example, you can use `[(ngModel)]` only
|
||||
after importing the Angular `FormsModule`.
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td style="vertical-align: top">
|
||||
<code>exports</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
|
||||
A list of declarations—*component*, *directive*, and *pipe* classes—that
|
||||
an importing module can use.
|
||||
|
||||
Exported declarations are the module's _public API_.
|
||||
A component in another module can [use](guide/ngmodule-faq#q-template-reference) _this_ module's `UserComponent`
|
||||
if it imports this module and this module exports `UserComponent`.
|
||||
|
||||
Declarations are private by default.
|
||||
If this module does _not_ export `UserComponent`, than only the components within where the `UserComponent` has been declared can use `UserComponent.
|
||||
|
||||
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.
|
||||
|
||||
A module can list another module among its `exports`, in which case
|
||||
all of that module's public components, directives, and pipes are exported.
|
||||
|
||||
[Re-export](guide/ngmodule-faq#q-reexport) 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`.
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td style="vertical-align: top">
|
||||
<code>bootstrap</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
|
||||
A list of components that are automatically bootstrapped.
|
||||
|
||||
Usually there's only one component in this list, the _root component_ of the application.
|
||||
|
||||
Angular can launch with multiple bootstrap components,
|
||||
each with its own location in the host web page.
|
||||
|
||||
A bootstrap component is automatically added to `entryComponents`.
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
<td style="vertical-align: top">
|
||||
<code>entryComponents</code>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
|
||||
|
||||
A list of components that can be dynamically loaded into the view.
|
||||
|
||||
By default, an Angular app always has at least one entry component, the root component, `AppComponent`. Its purpose is to serve as a point of entry into the app, that is, you bootstrap it to launch the app.
|
||||
|
||||
Routed components are also _entry components_ because they need to be loaded dynamically.
|
||||
The router creates them and drops them into the DOM near a `<router-outlet>`.
|
||||
|
||||
While the bootstrapped and routed components are _entry components_,
|
||||
you don't have to add them to a module's `entryComponents` list,
|
||||
as they are added implicitly.
|
||||
|
||||
Angular automatically adds components in the module's `bootstrap` and route definitions into the `entryComponents` list.
|
||||
|
||||
That leaves only components bootstrapped using one of the imperative techniques, such as [`ViewComponentRef.createComponent()`](https://angular.io/api/core/ViewContainerRef#createComponent) as undiscoverable.
|
||||
|
||||
Dynamic component loading is not common in most apps beyond the router. If you need to dynamically load components, you must add these components to the `entryComponents` list yourself.
|
||||
|
||||
For more information, see [Entry Components](guide/entry-components).
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
## More on NgModules
|
||||
|
||||
You may also be interested in the following:
|
||||
* [Feature Modules](guide/feature-modules).
|
||||
* [Entry Components](guide/entry-components).
|
||||
* [Providers](guide/providers).
|
||||
* [Types of NgModules](guide/module-types).
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
80
aio/content/guide/ngmodule-vs-jsmodule.md
Normal file
80
aio/content/guide/ngmodule-vs-jsmodule.md
Normal file
@ -0,0 +1,80 @@
|
||||
# JavaScript Modules vs. NgModules
|
||||
|
||||
#### Prerequisites
|
||||
A basic understanding of [Bootstrapping](guide/bootstrapping).
|
||||
|
||||
<hr>
|
||||
|
||||
JavaScript and Angular use modules to organize code, and
|
||||
though they organize it differently, Angular apps rely on both.
|
||||
|
||||
## JavaScript modules
|
||||
|
||||
In JavaScript, modules are individual files with JavaScript code in them. To make what’s in them available, you write an export statement, usually after the relevant code, like this:
|
||||
|
||||
```javascript
|
||||
export class AppComponent { ... }
|
||||
```
|
||||
|
||||
Then, when you need that file’s code in another file, you import it like this:
|
||||
|
||||
```javascript
|
||||
import { AppComponent } from './app.component';
|
||||
```
|
||||
|
||||
JavaScript modules help you namespace, preventing accidental global variables.
|
||||
|
||||
## NgModules
|
||||
|
||||
<!-- KW-- perMisko: let's discuss. This does not answer the question why it is different. Also, last sentence is confusing.-->
|
||||
NgModules are classes decorated with `@NgModule`. The `@NgModule` decorator’s `imports` array tells Angular what other NgModules the current module needs. The modules in the imports array are different than JavaScript modules because they are NgModules rather than regular JavaScript modules. Classes with an `@NgModule` decorator are by convention kept in their own files, but what makes them an `NgModule` isn’t being in their own file, like JavaScript modules; it’s the presence of `@NgModule` and its metadata.
|
||||
|
||||
The `AppModule` generated from the Angular CLI demonstrates both kinds of modules in action:
|
||||
|
||||
```javascript
|
||||
/* These are JavaScript import statements. Angular doesn’t know anything about these. */
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpModule } from '@angular/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
/* The @NgModule decorator lets Angular know that this is an NgModule. */
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
imports: [ /* These are NgModule imports. */
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpModule
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
```
|
||||
|
||||
|
||||
The NgModule classes differ from JavaScript module classes 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.
|
||||
* An NgModule can only export the [declarable classes](guide/ngmodule-faq#q-declarable)
|
||||
it owns or imports from other modules. It doesn't declare or export any other kind of class.
|
||||
* Unlike JavaScript modules, an NgModule can extend the _entire_ application with services
|
||||
by adding providers to the `@NgModule.providers` list.
|
||||
|
||||
<hr />
|
||||
|
||||
## More on NgModules
|
||||
|
||||
For more information on NgModules, see:
|
||||
* [Bootstrapping](guide/bootstrapping).
|
||||
* [Frequently used modules](guide/frequent-ngmodules).
|
||||
* [Providers](guide/providers).
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
75
aio/content/guide/ngmodules.md
Normal file
75
aio/content/guide/ngmodules.md
Normal file
@ -0,0 +1,75 @@
|
||||
# NgModules
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
A basic understanding of the following concepts:
|
||||
* [Bootstrapping](guide/bootstrapping).
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
|
||||
<hr>
|
||||
|
||||
**NgModules** configure the injector and the compiler and help organize related things together
|
||||
|
||||
An NgModule is a class marked by the `@NgModule` decorator.
|
||||
`@NgModule` takes a metadata object that describes how to compile a component's templates and how to create an injector at runtime.
|
||||
It identifies the module's own components, directives, and pipes,
|
||||
making some of them public, through the `exports` property public, so that external components can use them.
|
||||
`@NgModule` can also add service providers to the application dependency injectors.
|
||||
|
||||
For an example app showcasing all the techniques that NgModules related pages
|
||||
cover, see the <live-example></live-example>. For explanations on the individual techniques, visit the relevant NgModule pages under the NgModules
|
||||
section.
|
||||
|
||||
|
||||
## Angular modularity
|
||||
|
||||
Modules are a great way to organize an application and extend it with capabilities from external libraries.
|
||||
|
||||
Angular libraries are NgModules, such as `FormsModule`, `HttpModule`, and `RouterModule`.
|
||||
Many third-party libraries are available as NgModules such as
|
||||
<a href="https://material.angular.io/">Material Design</a>,
|
||||
<a href="http://ionicframework.com/">Ionic</a>, and
|
||||
<a href="https://github.com/angular/angularfire2">AngularFire2</a>.
|
||||
|
||||
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.
|
||||
Such services might be internally developed, like something you'd develop yourself or come from outside sources, such as the Angular router and HTTP client.
|
||||
|
||||
Modules can be loaded eagerly when the application starts or lazy loaded asynchronously by the router.
|
||||
|
||||
NgModule metadata does the following:
|
||||
|
||||
* Declares which components, directives, and pipes belong to the module.
|
||||
* Makes some of those components, directives, and pipes public so that other module's component templates can use them.
|
||||
* Imports other modules with the components, directives, and pipes that components in the current module need.
|
||||
* Provides services at the other application components can use.
|
||||
|
||||
Every Angular app has at least one module, the root module.
|
||||
You [bootstrap](guide/bootstrapping) 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](guide/feature-modules)
|
||||
that represent collections of related functionality.
|
||||
You then import these modules into the root module.
|
||||
|
||||
## The basic NgModule
|
||||
|
||||
The CLI generates the following basic app module when creating a new app.
|
||||
|
||||
<code-example path="bootstrapping/src/app/app.module.ts" region="whole-ngmodule" title="src/app/app.module.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
At the top are the import statements. The next section is where you configure the `@NgModule` by stating what components and directives belong to it (`declarations`) as well as which other modules it uses (`imports`). This page builds on [Bootstrapping](guide/bootstrapping), which covers the structure of an NgModule in detail. If you need more information on the structure of an `@NgModule`, be sure to read [Bootstrapping](guide/bootstrapping).
|
||||
|
||||
<hr />
|
||||
|
||||
## More on NgModules
|
||||
|
||||
You may also be interested in the following:
|
||||
* [Feature Modules](guide/feature-modules).
|
||||
* [Entry Components](guide/entry-components).
|
||||
* [Providers](guide/providers).
|
||||
* [Types of NgModules](guide/module-types).
|
75
aio/content/guide/providers.md
Normal file
75
aio/content/guide/providers.md
Normal file
@ -0,0 +1,75 @@
|
||||
# Providers
|
||||
|
||||
#### Prerequisites:
|
||||
* A basic understanding of [Bootstrapping](guide/bootstrapping).
|
||||
* Familiarity with [Frequently Used Modules](guide/frequent-ngmodules).
|
||||
|
||||
For the final sample app using the provider that this page describes,
|
||||
see the <live-example></live-example>.
|
||||
|
||||
<hr>
|
||||
|
||||
## Create a service
|
||||
You can provide services to your app by using the providers array in an NgModule.
|
||||
Consider the default app generated by the CLI. In order to add
|
||||
a user service to it,
|
||||
you can generate one by entering the following command in the terminal window:
|
||||
|
||||
```sh
|
||||
ng generate service User
|
||||
```
|
||||
|
||||
This creates a service called `UserService` and returns a message telling you
|
||||
that you need to provide it. Update `app.module.ts` by importing it with your
|
||||
other import statements at the top of the file and adding it to the providers array:
|
||||
|
||||
<code-example path="providers/src/app/app.module.ts" region="app-module" title="src/app/app.module.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
|
||||
## Provider scope
|
||||
|
||||
When you add a service provider to the providers array of the root module, it’s available throughout the app. Additionally, when you import a module that has providers, those providers are also available to all the classes in the app as long they have the lookup token. For example, if you import the `HttpModule` into your `AppModule`, its providers are then available to the entire app and you can make HTTP requests from anywhere in your app.
|
||||
|
||||
|
||||
## Limiting provider scope by lazy loading modules
|
||||
|
||||
In the basic CLI generated app, modules are eagerly loaded which means that they are all loaded when the app launches. Angular uses an injector system to make things available between modules. In an eagerly loaded app, the root application injector makes all of the providers in all of the modules available throughout the app.
|
||||
|
||||
This behavior necessarily changes when you use lazy loading. Lazy loading is when you load modules only when you need them; for example, when routing. They aren’t loaded right away like with eagerly loaded modules. This means that any services listed in their provider arrays aren’t available because the root injector doesn’t know about these modules.
|
||||
|
||||
<!-- KW--Make diagram here -->
|
||||
<!-- KW--per Misko: not clear if the lazy modules are siblings or grand-children. They are both depending on router structure. -->
|
||||
When the Angular router lazy-loads a module, it creates a new injector. This injector is a child of the root application injector. Imagine a tree of injectors; there is a single root injector and then a child injector for each lazy loaded module. The router adds all of the providers from the root injector to the child injector. 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.
|
||||
|
||||
Any component created within a lazy loaded 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.
|
||||
|
||||
Though you can provide services by lazy loading modules, not all services can be lazy loaded. For instance, some modules only work in the root module, such as the Router. The Router works with the global location object in the browser.
|
||||
|
||||
|
||||
## Limiting provider scope with components
|
||||
|
||||
Another way to limit provider scope is by adding the service you want to limit to the component’s provider array. Component providers and NgModule providers are independent of each other. This method is helpful for when you want to eagerly load a module that needs a service all to itself. Providing a service in the component limits the service only to that component (other components in the same module can’t access it.)
|
||||
|
||||
|
||||
## Providing services in modules vs. components
|
||||
|
||||
Generally, provide services the whole app needs in the root module and scope services by providing them in lazy loaded modules.
|
||||
|
||||
The router works at the root level so if you put providers in a component, even `AppComponent`, lazy loaded modules, which rely on the router, can’t see them.
|
||||
|
||||
<!-- KW--Make a diagram here -->
|
||||
Register a provider with a component when you must limit a service instance to a component and its component tree, that is, its child components. For example, a customer editing component, `UserEditorComponent`, that needs a private copy of a caching `UserService` should register the `UserService` with the `UserEditorComponent`. Then each new instance of the `UserEditorComponent` gets its own cached service instance.
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
## More on NgModules
|
||||
|
||||
You may also be interested in:
|
||||
* [Singleton Services](guide/singleton-services), which elaborates on the concepts covered on this page.
|
||||
* [Lazy Loading Modules](guide/lazy-loading-ngmodules).
|
||||
* [NgModule FAQ](guide/ngmodule-faq).
|
||||
|
||||
|
||||
|
@ -1274,7 +1274,7 @@ The **Routing Module** has several characteristics:
|
||||
* Separates routing concerns from other application concerns.
|
||||
* Provides a module to replace or remove when testing the application.
|
||||
* Provides a well-known location for routing service providers including guards and resolvers.
|
||||
* Does **not** [declare components](guide/ngmodule-faq#routing-module).
|
||||
* Does **not** declare components.
|
||||
|
||||
|
||||
{@a routing-refactor}
|
||||
|
@ -270,7 +270,7 @@ The following are all in `src/`
|
||||
|
||||
|
||||
Compiles the application with the [JIT compiler](guide/glossary#jit) and
|
||||
[bootstraps](guide/bootstrapping#main "bootstrap the application")
|
||||
[bootstraps](guide/bootstrapping)
|
||||
the application's main module (`AppModule`) to run in the browser.
|
||||
The JIT compiler is a reasonable choice during the development of most projects and
|
||||
it's the only viable choice for a sample running in a _live-coding_ environment like Plunker.
|
||||
|
76
aio/content/guide/sharing-ngmodules.md
Normal file
76
aio/content/guide/sharing-ngmodules.md
Normal file
@ -0,0 +1,76 @@
|
||||
# Sharing Modules
|
||||
|
||||
#### Prerequisites
|
||||
A basic understanding of the following:
|
||||
* [Feature Modules](guide/feature-modules).
|
||||
* [JavaScript Modules vs. NgModules](guide/ngmodule-vs-jsmodule).
|
||||
* [Frequently Used Modules](guide/frequent-ngmodules).
|
||||
* [Routing and Navigation](guide/router).
|
||||
* [Lazy loading modules](guide/lazy-loading-ngmodules).
|
||||
|
||||
|
||||
<!--* Components (#TBD) We don’t have a page just on the concept of components, but I think one would be helpful for beginners.-->
|
||||
|
||||
<hr>
|
||||
|
||||
Creating shared modules allows you to organize and streamline your code. You can put commonly
|
||||
used directives, pipes, and components into one module and then import just that module wherever
|
||||
you need it in other parts of your app.
|
||||
|
||||
Consider the following module from an imaginary app:
|
||||
|
||||
|
||||
```typescript
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { OrdersPipe } from './orders.pipe';
|
||||
import { NewItemDirective } from './newitem.directive';
|
||||
@NgModule({
|
||||
imports: [ CommonModule ],
|
||||
declarations: [ OrdersPipe, NewItemDirective ],
|
||||
exports: [ OrdersPipe, NewItemDirective,
|
||||
CommonModule, FormsModule ]
|
||||
})
|
||||
export class SharedModule { }
|
||||
```
|
||||
|
||||
Note the following:
|
||||
|
||||
* It imports the `CommonModule` because the module's component needs common directives.
|
||||
* It declares and exports the utility pipe, directive, and component classes.
|
||||
* It re-exports the `CommonModule` and `FormsModule`.
|
||||
|
||||
By re-exporting `CommonModule` and `FormsModule`, any other module that imports this
|
||||
`SharedModule`, gets access to directives like `NgIf` and `NgFor` from `CommonModule`
|
||||
and can bind to component properties with `[(ngModel)]`, a directive in the `FormsModule`.
|
||||
|
||||
Even though the components declared by `SharedModule` might not bind
|
||||
with `[(ngModel)]` and there may be no need for `SharedModule`
|
||||
to import `FormsModule`, `SharedModule` can still export
|
||||
`FormsModule` without listing it among its `imports`. This
|
||||
way, you can give other modules access to `FormsModule` without
|
||||
having to import it directly into the `@NgModule` decorator.
|
||||
|
||||
### Using components vs services from other modules.
|
||||
|
||||
There is an important distinction between using another module's component and
|
||||
using a service from another module.. Import modules when you want to use
|
||||
directives, pipes, and components. Importing a module with services means that you will have a new instance of that service, which typically is not what you need, (typically one wants to reuse an existing service.) Use module imports to control service instantiation.
|
||||
|
||||
The most common way to get a hold of sharedservices is through Angular
|
||||
[dependency injection](guide/dependency-injection), rather than through the module system (importing a module will result in a new service instance, which is not a typical usage).
|
||||
|
||||
To read about sharing services, see [Providers](guide/providers).
|
||||
|
||||
|
||||
<hr />
|
||||
|
||||
## More on NgModules
|
||||
|
||||
You may also be interested in the following:
|
||||
* [Providers](guide/providers).
|
||||
* [Types of Modules](guide/module-types).
|
||||
|
||||
|
||||
|
179
aio/content/guide/singleton-services.md
Normal file
179
aio/content/guide/singleton-services.md
Normal file
@ -0,0 +1,179 @@
|
||||
# Singleton services
|
||||
|
||||
#### Prerequisites:
|
||||
|
||||
* A basic understanding of [Bootstrapping](guide/bootstrapping).
|
||||
* Familiarity with [Providers](guide/providers).
|
||||
|
||||
For a sample app using the app-wide singleton service
|
||||
that this page describes, see the
|
||||
<live-example name="ngmodules">live example</live-example>
|
||||
showcasing all the documented features of NgModules.
|
||||
|
||||
<hr />
|
||||
|
||||
## Providing a singleton service
|
||||
|
||||
An injector created from a module definition will have services which are singletons with respect to that injector. To control the lifetime of services, one controls the creation and destruction of injectors. For example, a route will have an associated module. When the route is activated, an injector is created from that module as a child of the current injector. When you navigate away from the route, the injector is destroyed. This means that services declared in a route module will have a lifetime equal to that of the route. Similarly, services provided in an application module will have the same lifetime of the application, hence singleton.
|
||||
|
||||
The following example module is called, as a convention, `CoreModule`. This use of `@NgModule` creates organizational infrastructure and gives you
|
||||
a way of providing services from a designated NgModule.
|
||||
|
||||
<code-example path="providers/src/app/core/core.module.ts" region="" title="src/app/core/core.module.ts" linenums="false">
|
||||
</code-example>
|
||||
|
||||
Here, `CoreModule` provides the `UserService`, and because `AppModule`
|
||||
imports `CoreModule`, any services that `CoreModule` provides are available
|
||||
throughout the app, because it is a root of the injector tree. It will also be a singleton because the injector lifetime of the `AppModule` is for the duration of the application.
|
||||
|
||||
Angular registers the `UserService` 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.
|
||||
|
||||
The root `AppModule` could register the `UserService` directly,
|
||||
but as the app grows, it could have other services and
|
||||
components like spinners, modals, and so on. To
|
||||
keep your app organized, consider using a module such as `CoreModule`.
|
||||
This technique simplifies the root `AppModule` in its
|
||||
capacity as orchestrator of the application as a whole.
|
||||
|
||||
Now you can inject such services into components as needed. In terms of
|
||||
Angular NgModules, you only need to define the services in one `@NgModule`.
|
||||
See [JS Modules vs. NgModules](guide/ngmodule-vs-jsmodule) for
|
||||
more information on how to differentiate between the two.
|
||||
|
||||
As a general rule, import modules with providers _exactly once_,
|
||||
preferably in the application's _root module_.
|
||||
That's also usually the best place to configure, wrap, and override them.
|
||||
|
||||
For more detailed information on services, see
|
||||
[part 5](tutorial/toh-pt4) of the [Tour of Heroes tutorial](tutorial).
|
||||
|
||||
|
||||
## `forRoot()`
|
||||
|
||||
If a module provides both providers and declarations (components, directives, pipes) then loading it in a child injector such as a route, would duplicate the provider instances. The duplication of providers would cause issues as they would shadow the root instances, which are probably meant to be singletons. For this reason Angular provides a way to separate providers out of the module so that same module can be imported into the root module with `providers` and child modules without `providers`.
|
||||
|
||||
1. Create a static method `forRoot()` (by convention) on the module.
|
||||
2. Place the providers into the `forRoot` method as follows.
|
||||
|
||||
<!-- MH: show a simple example how to do that without going to deep into it. -->
|
||||
|
||||
To make this more concrete, consider the `RouterModule` as an example. `RouterModule` needs to provide the `Router` service, as well as the `RouterOutlet` directive. `RouterModule` has to be imported by the root application module so that the application has a `Router` and the application has at least one `RouterOutlet`. It also must be imported by the individual route components so that they can place `RouterOutlet` directives into their template for sub-routes.
|
||||
|
||||
If the `RouterModule` didn’t have `forRoot()` then each route component would instantiate a new `Router` instance, which would break the application as there can only be one `Router`. For this reason, the `RouterModule` has the `RouterOutlet` declaration so that it is available everywhere, but the `Router` provider is only in the `forRoot()`. The result is that the root application module imports `RouterModule.forRoot(...)` and gets a `Router`, whereas all route components import `RouterModule` which does not include the `Router`.
|
||||
|
||||
If you have a module which provides both providers and declarations, use this pattern to separate them out.
|
||||
|
||||
A module that adds providers to the application can offer a
|
||||
facility for configuring those providers as well through the
|
||||
`forRoot()` method.
|
||||
|
||||
`forRoot()` takes a service configuration object and returns a
|
||||
[ModuleWithProviders](api/core/ModuleWithProviders), which is
|
||||
a simple object with the following properties:
|
||||
|
||||
* `ngModule`: in this example, the `CoreModule` class.
|
||||
* `providers`: the configured providers.
|
||||
|
||||
In the <live-example name="ngmodules">live example</live-example>
|
||||
the root `AppModule` imports the `CoreModule` and adds the
|
||||
`providers` to the `AppModule` providers. Specifically,
|
||||
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.
|
||||
|
||||
Import `CoreModule` and use its `forRoot()` method one time, in `AppModule`, because it registers services and you only want to register those services one time in your app. If you were to register them more than once, you could end up with multiple instances of the service and a runtime error.
|
||||
|
||||
You can also add a `forRoot()` method in the `CoreModule` that configures
|
||||
the core `UserService`.
|
||||
|
||||
In the following example, the optional, injected `UserServiceConfig`
|
||||
extends the core `UserService`. If a `UserServiceConfig` exists, the `UserService` sets the user name from that config.
|
||||
|
||||
<code-example path="ngmodules/src/app/core/user.service.ts" region="ctor" title="src/app/core/user.service.ts (constructor)" linenums="false">
|
||||
|
||||
</code-example>
|
||||
|
||||
Here's `forRoot()` that takes a `UserServiceConfig` object:
|
||||
|
||||
<code-example path="ngmodules/src/app/core/core.module.ts" region="for-root" title="src/app/core/core.module.ts (forRoot)" linenums="false">
|
||||
|
||||
</code-example>
|
||||
|
||||
Lastly, call it within the `imports` list of the `AppModule`.
|
||||
|
||||
<code-example path="ngmodules/src/app/app.module.ts" region="import-for-root" title="src/app/app.module.ts (imports)" linenums="false">
|
||||
|
||||
</code-example>
|
||||
|
||||
The app displays "Miss Marple" as the user instead of the default "Sherlock Holmes".
|
||||
|
||||
Remember to _import_ `CoreModule` as a Javascript import at the top of the file; don't add it to more than one `@NgModule` `imports` list.
|
||||
|
||||
<!-- KW--Does this mean that if we need it elsewhere we only import it at the top? I thought the services would all be available since we were importing it into `AppModule` in `providers`. -->
|
||||
|
||||
## Prevent reimport of the `CoreModule`
|
||||
|
||||
Only the root `AppModule` should import the `CoreModule`. If a
|
||||
lazy-loaded module imports it too, the app can generate
|
||||
[multiple instances](guide/ngmodule-faq#q-why-bad) of a service.
|
||||
|
||||
To guard against a lazy-loaded module re-importing `CoreModule`, add the following `CoreModule` constructor.
|
||||
|
||||
<code-example path="ngmodules/src/app/core/core.module.ts" region="ctor" title="src/app/core/core.module.ts" linenums="false">
|
||||
|
||||
</code-example>
|
||||
|
||||
The constructor tells Angular to inject the `CoreModule` into itself.
|
||||
The injection would be circular if Angular looked for
|
||||
`CoreModule` in the _current_ injector. The `@SkipSelf`
|
||||
decorator means "look for `CoreModule` in an ancestor
|
||||
injector, above me in the injector hierarchy."
|
||||
|
||||
If the constructor executes as intended in the `AppModule`,
|
||||
there would be no ancestor injector that could provide an instance of `CoreModule` and the injector should give up.
|
||||
|
||||
By default, the injector throws an error when it can't
|
||||
find a requested provider.
|
||||
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 `CustomersModule`.
|
||||
|
||||
Angular creates a lazy-loaded module 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.
|
||||
|
||||
Here are the two files in their entirety for reference:
|
||||
|
||||
<code-tabs linenums="false">
|
||||
<code-pane
|
||||
title="app.module.ts"
|
||||
path="ngmodules/src/app/app.module.ts">
|
||||
</code-pane>
|
||||
<code-pane
|
||||
title="core.module.ts"
|
||||
region="whole-core-module"
|
||||
path="ngmodules/src/app/core/core.module.ts">
|
||||
</code-pane>
|
||||
</code-tabs>
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
## More on NgModules
|
||||
|
||||
You may also be interested in:
|
||||
* [Sharing NgModules](guide/singleton-services), which elaborates on the concepts covered on this page.
|
||||
* [Lazy Loading Modules](guide/lazy-loading-ngmodules).
|
||||
* [NgModule FAQ](guide/ngmodule-faq).
|
||||
|
||||
|
||||
|
@ -415,7 +415,7 @@ and re-attach it to a dynamically-constructed Angular test module
|
||||
tailored specifically for this battery of tests.
|
||||
|
||||
The `configureTestingModule` method takes an `@NgModule`-like metadata object.
|
||||
The metadata object can have most of the properties of a normal [NgModule](guide/ngmodule).
|
||||
The metadata object can have most of the properties of a normal [NgModule](guide/ngmodules).
|
||||
|
||||
_This metadata object_ simply declares the component to test, `BannerComponent`.
|
||||
The metadata lack `imports` because (a) the default testing module configuration already has what `BannerComponent` needs
|
||||
@ -1782,7 +1782,7 @@ It's a bit tighter and smaller, with fewer import statements (not shown).
|
||||
|
||||
### Import the feature module
|
||||
|
||||
The `HeroDetailComponent` is part of the `HeroModule` [Feature Module](guide/ngmodule#feature-modules) that aggregates more of the interdependent pieces
|
||||
The `HeroDetailComponent` is part of the `HeroModule` [Feature Module](guide/feature-modules) that aggregates more of the interdependent pieces
|
||||
including the `SharedModule`.
|
||||
Try a test configuration that imports the `HeroModule` like this one:
|
||||
|
||||
|
@ -387,7 +387,7 @@ bootstrapping the AngularJS module.
|
||||
|
||||
<div class="l-sub-section">
|
||||
|
||||
Read more about [NgModules](guide/ngmodule).
|
||||
For more information, see [NgModules](guide/ngmodules).
|
||||
|
||||
</div>
|
||||
|
||||
|
Reference in New Issue
Block a user