Simplified routing in tutorial example Updated ngmodule guide and ngmodule faq with routing module prose
		
			
				
	
	
		
			1052 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			1052 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| block includes
 | |
|   include ../_util-fns
 | |
| 
 | |
| // TODO
 | |
|   Images
 | |
| 
 | |
| :marked
 | |
|   **Angular Modules** help organize an application into cohesive blocks of functionality.
 | |
| 
 | |
|   An Angular Module is a _class_ adorned with the **@NgModule** decorator function.
 | |
|   `@NgModule` takes a metadata object that tells Angular how to compile and run module code.
 | |
|   It identifies the module's _own_ components, directives and pipes,
 | |
|   making some of them public so external components can use them.
 | |
|   It may add service providers to the application dependency injectors.
 | |
|   And there are more options covered here.
 | |
| 
 | |
|   This page explains how to **create** `NgModule` classes and how to load them,
 | |
|   either immediately when the application launches or later, as needed, via the [Router](router.html).
 | |
| 
 | |
|   ## Table of Contents
 | |
|   * [Angular modularity](#angular-modularity "Add structure to the app with NgModule")
 | |
|   * [The application root module](#root-module "The startup module that every app requires")
 | |
|   * [Bootstrap](#bootstrap "Launch the app in a browser with the root module as the entry point") the root module
 | |
|   * [Declarations](#declarations "Declare the components, directives, and pipes that belong to a module")
 | |
|   * [Providers](#providers "Extend the app with additional services")
 | |
|   * [Imports](#imports "Import components, directives, and pipes for use in component templates")
 | |
|   * [Resolve conflicts](#resolve-conflicts "When two directives have the same selector ...")
 | |
|   * [Feature modules](#feature-modules "Partition the app into feature modules")
 | |
|   * [Lazy loaded modules](#lazy-load "Load modules asynchronously") with the Router
 | |
|   * [Shared modules](#shared-module "Create modules for commonly used components, directives, and pipes")
 | |
|   * [The Core module](#core-module "Create a core module with app-wide singleton services and single-use components")
 | |
|   * [Configure core services with _forRoot_](#core-for-root "Configure providers during module import")
 | |
|   * [Prevent reimport of the _CoreModule_](#prevent-reimport "because bad things happen if a lazy loaded module imports Core")
 | |
|   * [NgModule metadata properties](#ngmodule-properties "A technical summary of the @NgModule metadata properties")
 | |
| 
 | |
|   ### Live examples
 | |
|   This page explains Angular Modules through a progression of improvements to a sample with a "Tour of Heroes" theme.
 | |
|   Here's an index to live examples at key moments in the evolution of that sample:
 | |
| 
 | |
|   * <live-example plnkr="minimal.0">A minimal NgModule app</live-example>
 | |
|   * <live-example plnkr="contact.1b">The first contact module</live-example>
 | |
|   * <live-example plnkr="contact.2">The revised contact module</live-example>
 | |
|   * <live-example plnkr="pre-shared.3">Just before adding _SharedModule_</live-example>
 | |
|   * <live-example>The final version</live-example>
 | |
| 
 | |
|   ### Frequently Asked Questions (FAQs)
 | |
| 
 | |
|   This page covers Angular Module concepts in a tutorial fashion.
 | |
| 
 | |
|   The companion [Angular Module FAQs](../cookbook/ngmodule-faq.html "Angular Module FAQs") cookbook
 | |
|   offers ready answers to specific design and implementation questions.
 | |
|   Read this page first before hopping over to those FAQs.
 | |
| 
 | |
| .l-hr
 | |
| 
 | |
| a#angular-modularity
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Angular Modularity
 | |
| 
 | |
|   Modules are a great way to organize the application and extend it with capabilities from external libraries.
 | |
| 
 | |
|   Many Angular libraries are modules (e.g, `FormsModule`, `HttpModule`, `RouterModule`).
 | |
|   Many third party libraries are available as Angular modules (e.g.,
 | |
|   <a href="https://material.angular.io/" target="_blank">Material Design</a>,
 | |
|   <a href="http://ionicframework.com/" target="_blank">Ionic</a>,
 | |
|   <a href="https://github.com/angular/angularfire2" target="_blank">AngularFire2</a>).
 | |
| 
 | |
|   Angular modules 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 such as the application logger.
 | |
|   They can come from outside sources such as the Angular router and Http client.
 | |
| 
 | |
|   Modules can be loaded eagerly when the application starts.
 | |
|   They can also be _lazy loaded_ asynchronously by the router.
 | |
| 
 | |
|   An Angular module is a class decorated with `@NgModule` metadata. The metadata:
 | |
| 
 | |
|   * declare which components, directives and pipes  _belong_ to the module.
 | |
|   * make some of those classes public so that other component templates can use them.
 | |
|   * import other modules with the components, directives and pipes needed by the components in _this_ module.
 | |
|   * provide services at the application level that any application component can use.
 | |
| 
 | |
|   Every Angular app has at least one module class, the _root module_.
 | |
|   We bootstrap that module to launch the application.
 | |
| 
 | |
|   The _root module_ is all we need in a simple application with a few components.
 | |
|   As the app grows, we refactor the _root module_ into **feature modules**
 | |
|   that represent collections of related functionality.
 | |
|   We then import these modules into the _root module_.
 | |
| 
 | |
|   We'll see how later in the page. Let's start with the _root module_.
 | |
| 
 | |
| a#root-module
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## _AppModule_ - the application root module
 | |
| 
 | |
|   Every Angular app has a **root module** class.
 | |
|   By convention it's a class called `AppModule` in a file named `app.module.ts`.
 | |
| 
 | |
|   This `AppModule` is about as minimal as it gets:
 | |
| +makeExample('ngmodule/ts/app/app.module.0.ts', '', 'app/app.module.ts (minimal)')(format=".")
 | |
| :marked
 | |
|   The `@NgModule` decorator defines the metadata for the module.
 | |
|   We'll take an intuitive approach to understanding the metadata and fill in details as we go.
 | |
| 
 | |
|   This metadata imports a single helper module, `BrowserModule`, the module every browser app must import.
 | |
| 
 | |
|   `BrowserModule` registers critical application service providers.
 | |
|   It also includes common directives like `NgIf` and `NgFor` which become immediately visible and usable
 | |
|   in any of this modules component templates.
 | |
| 
 | |
|   The `declarations` list identifies the application's only component,
 | |
|   the _root component_, the top of this app's rather bare component tree.
 | |
| 
 | |
|   The example `AppComponent` simply displays a data-bound title:
 | |
| +makeExample('ngmodule/ts/app/app.component.0.ts', '', 'app/app.component.ts (minimal)')(format=".")
 | |
| :marked
 | |
|   Lastly, the `@NgModule.bootstrap` property identifies this `AppComponent` as the _bootstrap component_.
 | |
|   When Angular launches the app, it places the HTML rendering of `AppComponent` in the DOM,
 | |
|   inside the `<my-app>` element tags of the `index.html`
 | |
| 
 | |
| a#bootstrap
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Bootstrapping in _main.ts_
 | |
|   We launch the application by bootstrapping the `AppModule` in the `main.ts` file.
 | |
| 
 | |
|   Angular offers a variety of bootstrapping options, targeting multiple platforms.
 | |
|   In this page we consider two options, both targeting the browser.
 | |
| 
 | |
|   ### Dynamic bootstrapping with the Just-in-time (JiT) compiler
 | |
|   In the first, _dynamic_ option, the [Angular compiler](../cookbook/ngmodule-faq.html#q-angular-compiler "About the Angular Compiler")
 | |
|   compiles the application in the browser and then launches the app.
 | |
| 
 | |
| +makeExample('ngmodule/ts/app/main.ts', '', 'app/main.ts (dynamic)')(format=".")
 | |
| :marked
 | |
|   The samples in this page demonstrate the dynamic bootstrapping approach.
 | |
| 
 | |
|   <live-example embedded plnkr="minimal.0" img="devguide/ngmodule/minimal-plunker.png">Try the live example.</live-example>
 | |
| 
 | |
| 
 | |
|   ### Static bootstrapping with the Ahead-Of-time (AoT) compiler
 | |
| 
 | |
|   Consider the static alternative which can produce a much smaller application that
 | |
|   launches faster, especially on mobile devices and high latency networks.
 | |
| 
 | |
|   In the _static_ option, the Angular compiler runs ahead-of-time as part of the build process,
 | |
|   producing a collection of class factories in their own files.
 | |
|   Among them is the `AppModuleNgFactory`.
 | |
| 
 | |
|   The syntax for bootstrapping the pre-compiled `AppModuleNgFactory` is similar to
 | |
|   the dynamic version that bootstraps the `AppModule` class.
 | |
| 
 | |
| +makeExample('ngmodule/ts/app/main-static.ts', '', 'app/main.ts (static)')(format=".")
 | |
| :marked
 | |
|   Because the entire application was pre-compiled,
 | |
|   we don't ship the _Angular Compiler_ to the browser and we don't compile in the browser.
 | |
| 
 | |
|   The application code downloaded to the browser is much smaller than the dynamic equivalent
 | |
|   and it is ready to execute immediately. The performance boost can be significant.
 | |
| 
 | |
|   Both the JiT and AoT compilers generate an `AppModuleNgFactory` class from the same `AppModule`
 | |
|    source code.
 | |
|   The JiT compiler creates that factory class on the fly, in memory, in the browser.
 | |
|   The AoT compiler outputs the factory to a physical file
 | |
|   that we're importing here in the static version of `main.ts`.
 | |
| 
 | |
|   In general, the `AppModule` should neither know nor care how it is bootstrapped.
 | |
| 
 | |
|   Although the `AppModule` evolves as the app grows, the bootstrap code in `main.ts` doesn't change.
 | |
|   This is the last time we'll look at `main.ts`.
 | |
| 
 | |
| .l-hr
 | |
| 
 | |
| a#declarations
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Declare directives and components
 | |
|   The app evolves.
 | |
|   The first addition is a `HighlightDirective`, an [attribute directive](attribute-directives.html)
 | |
|   that sets the background color of the attached element.
 | |
| +makeExample('ngmodule/ts/app/highlight.directive.ts', '', 'app/highlight.directive.ts')(format=".")
 | |
| :marked
 | |
|   We update the `AppComponent` template to attach the directive to the title:
 | |
| +makeExample('ngmodule/ts/app/app.component.1.ts', 'template')(format=".")
 | |
| :marked
 | |
|   If we ran the app now, Angular would not recognize the `highlight` attribute and would ignore it.
 | |
|   We must declare the directive in `AppModule`.
 | |
| 
 | |
|   Import the `HighlightDirective` class and add it to the module's `declarations` like this:
 | |
| +makeExample('ngmodule/ts/app/app.module.1.ts', 'directive')(format=".")
 | |
| 
 | |
| :marked
 | |
|   ### Add a component
 | |
| 
 | |
|   We decide to refactor the title into its own `TitleComponent`.
 | |
|   The component's template binds to the component's `title` and `subtitle` properties like this:
 | |
| +makeExample('ngmodule/ts/app/title.component.html', 'v1', 'app/title.component.html')(format=".")
 | |
| 
 | |
| +makeExample('ngmodule/ts/app/title.component.ts', 'v1', 'app/title.component.ts')(format=".")
 | |
| 
 | |
| :marked
 | |
|   We rewrite the `AppComponent` to display the new `TitleComponent` in the `<app-title>` element,
 | |
|   using an input binding to set the `subtitle`.
 | |
| +makeExample('ngmodule/ts/app/app.component.1.ts', '', 'app/app.component.ts (v1)')(format=".")
 | |
| :marked
 | |
|   Angular won't recognize the `<app-title>` tag until we declare it in `AppModule`.
 | |
|   Import the `TitleComponent` class and add it to the module's `declarations`:
 | |
| +makeExample('ngmodule/ts/app/app.module.1.ts', 'component')(format=".")
 | |
| 
 | |
| a#providers
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Service Providers
 | |
| 
 | |
|   Modules are a great way to provide services for all of the module's components.
 | |
| 
 | |
|   The [Dependency Injection](dependency-injection.html) page describes
 | |
|   the Angular hierarchical dependency injection system and how to configure that system
 | |
|   with [providers](dependency-injection.html#providers) at different levels of the
 | |
|   application's component tree.
 | |
| 
 | |
|   A module can add providers to the application's root dependency injector, making those services
 | |
|   available everywhere in the application.
 | |
| 
 | |
|   Many applications capture information about the currently logged-in user and make that information
 | |
|   accessible through a user service.
 | |
|   This sample application has a dummy implementation of such a `UserService`.
 | |
| 
 | |
| +makeExample('ngmodule/ts/app/user.service.ts', '', 'app/user.service.ts')(format=".")
 | |
| :marked
 | |
|   The sample application should display a welcome message to the logged in user just below the application title.
 | |
|   Update the `TitleComponent` template to show the welcome message below the application title.
 | |
| +makeExample('ngmodule/ts/app/title.component.html', '', 'app/title.component.html')(format=".")
 | |
| :marked
 | |
|   Update the `TitleComponent` class with a constructor that injects the `UserService`
 | |
|   and sets the component's `user` property from the service.
 | |
| +makeExample('ngmodule/ts/app/title.component.ts', '', 'app/title.component.ts')(format=".")
 | |
| :marked
 | |
|   We've _defined_ and _used_ the service. Now we _provide_ it for all components to use by
 | |
|   adding it to a `providers` property in the `AppModule` metadata:
 | |
| +makeExample('ngmodule/ts/app/app.module.1.ts', 'providers', 'app/app.module.ts (providers)')(format=".")
 | |
| 
 | |
| a#imports
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Import supporting modules
 | |
| 
 | |
|   The app shouldn't welcome a user if there is no user.
 | |
| 
 | |
|   Notice in the revised `TitleComponent` that an `*ngIf` directive guards the message.
 | |
|   There is no message if there is no user.
 | |
| +makeExample('ngmodule/ts/app/title.component.html', 'ngIf', 'app/title.component.html (ngIf)')(format=".")
 | |
| :marked
 | |
|   Although `AppModule` doesn't declare `NgIf`, the application still compiles and runs.
 | |
|   How can that be? The Angular compiler should either ignore or complain about unrecognized HTML.
 | |
| 
 | |
|   Angular _does_ recognize `NgIf` because we imported it earlier.
 | |
|   The initial version of `AppModule` imports `BrowserModule`.
 | |
| +makeExample('ngmodule/ts/app/app.module.0.ts', 'imports', 'app/app.module.ts (imports)')(format=".")
 | |
| :marked
 | |
|   Importing `BrowserModule` made all of its public components, directives and pipes visible
 | |
|   to the component templates in `AppModule`. They are ready to use without further ado.
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     More accurately, `NgIf` is declared in `CommonModule` from `@angular/common`.
 | |
| 
 | |
|     `CommonModule` contributes many of the common directives that applications need including `ngIf` and `ngFor`.
 | |
| 
 | |
|     `BrowserModule` imports `CommonModule` and [_re-exports_](../cookbook/ngmodule-faq.html#q-re-export) it.
 | |
|     The net effect is that an importer of `BrowserModule` gets `CommonModule` directives automatically.
 | |
| :marked
 | |
|   Many familiar Angular directives do not belong to`CommonModule`.
 | |
|   For example,  `NgModel` and `RouterLink` belong to Angular's `FormsModule` and `RouterModule` respectively.
 | |
|   We must _import_ those modules before we can use their directives.
 | |
| 
 | |
|   To illustrate this point, we extend the sample app with `ContactComponent`,
 | |
|   a form component that imports form support from the Angular `FormsModule`.
 | |
| 
 | |
|   ### Add the _ContactComponent_
 | |
| 
 | |
|   [Angular Forms](forms.html) are a great way to manage user data entry.
 | |
| 
 | |
|   The `ContactComponent` presents a "contact editor",
 | |
|   implemented with _Angular Forms_ in the [_template-driven form_](forms.html) style.
 | |
| 
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     ### Angular Form Styles
 | |
| 
 | |
|     We write Angular form components in either the
 | |
|     [_template-driven form_](forms.html) style or
 | |
|     the [_reactive form_](../cookbook/dynamic-form.html) style.
 | |
| 
 | |
|     This sample is about to import the `FormsModule` from `@angular/forms` because
 | |
|     the `ContactComponent` is written in the _template-driven_ style.
 | |
|     Modules with components written in the _reactive_ style,
 | |
|     should import the `ReactiveFormsModule` instead.
 | |
| 
 | |
| :marked
 | |
|   The `ContactComponent` selector matches an element named `<app-contact>`.
 | |
|   Add an element with that name to the `AppComponent` template just below the `<app-title>`:
 | |
| +makeExample('ngmodule/ts/app/app.component.1b.ts', 'template', 'app/app.component.ts (template)')(format=".")
 | |
| 
 | |
| :marked
 | |
|   The `ContactComponent` has a lot going on.
 | |
|   Form components are often complex anyway and this one has its own `ContactService`,
 | |
|   its own [custom pipe](#pipes.html#custom-pipes) called `Awesome`,
 | |
|   and an alternative version of the `HighlightDirective`.
 | |
| 
 | |
|   To make it manageable, we place all contact-related material in an `app/contact` folder
 | |
|   and break the component into three constituent HTML, TypeScript, and css files:
 | |
| +makeTabs(
 | |
|   `ngmodule/ts/app/contact/contact.component.html,
 | |
|   ngmodule/ts/app/contact/contact.component.3.ts,
 | |
|   ngmodule/ts/app/contact/contact.component.css,
 | |
|   ngmodule/ts/app/contact/contact.service.ts,
 | |
|   ngmodule/ts/app/contact/awesome.pipe.ts,
 | |
|   ngmodule/ts/app/contact/highlight.directive.ts
 | |
|   `,
 | |
|   null,
 | |
|   `app/contact/contact.component.html,
 | |
|   app/contact/contact.component.ts,
 | |
|   app/contact/contact.component.css,
 | |
|   app/contact/contact.service.ts,
 | |
|   app/contact/awesome.pipe.ts,
 | |
|   app/contact/highlight.directive.ts
 | |
|   `)
 | |
| :marked
 | |
|   Focus on the component template.
 | |
|   Notice the two-way data binding `[(ngModel)]` in the middle of the template.
 | |
|   `ngModel` is the selector for the `NgModel` directive.
 | |
| 
 | |
|   Although `NgModel` is an Angular directive, the _Angular Compiler_ won't recognize it
 | |
|   because (a) `AppModule` doesn't declare it and (b) it wasn't imported via `BrowserModule`.
 | |
| 
 | |
|   Less obviously, even if Angular somehow recognized `ngModel`,
 | |
|   this `ContactComponent` would not behave like an Angular form because
 | |
|   form features such as validation are not yet available.
 | |
| 
 | |
|   ### Import the FormsModule
 | |
| 
 | |
|   Add the `FormsModule` to the `AppModule` metadata's `imports` list.
 | |
| +makeExample('ngmodule/ts/app/app.module.1.ts', 'imports')(format=".")
 | |
| :marked
 | |
|   Now `[(ngModel)]` binding will work and the user input will be validated by Angular Forms,
 | |
|   once we declare our new component, pipe and directive.
 | |
| 
 | |
| .alert.is-critical
 | |
|   :marked
 | |
|     **Do not** add `NgModel` — or the `FORMS_DIRECTIVES` —
 | |
|     to the `AppModule` metadata's declarations!
 | |
| 
 | |
|     These directives belong to the `FormsModule`.
 | |
|     Components, directives and pipes belong to one module — and _one module only_.
 | |
| 
 | |
|     **Never re-declare classes that belong to another module.**
 | |
| 
 | |
| a#declare-pipe
 | |
| :marked
 | |
|   ### Declare the contact component, directive and pipe
 | |
| 
 | |
|   The application fails to compile until we declare the contact component, directive and pipe.
 | |
|   Update the `declarations` in the  `AppModule` accordingly:
 | |
| +makeExample('ngmodule/ts/app/app.module.1.ts', 'declarations', 'app/app.module.ts (declarations)')(format=".")
 | |
| 
 | |
| a#import-name-conflict
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     There are two directives with the same name, both called `HighlightDirective`.
 | |
| 
 | |
|     We work around it by creating an alias for the second, contact version using the `as` JavaScript import keyword:
 | |
|   +makeExample('ngmodule/ts/app/app.module.1b.ts', 'import-alias')(format=".")
 | |
|   :marked
 | |
|     This solves the immediate problem of referencing both directive _types_ in the same file but
 | |
|     leaves another problem unresoved as we discuss [below](#resolve-conflicts).
 | |
| 
 | |
| :marked
 | |
|   ### Provide the _ContactService_
 | |
|   The `ContactComponent` displays contacts retrieved by the `ContactService`
 | |
|   which Angular injects into its constructor.
 | |
| 
 | |
|   We have to provide that service somewhere.
 | |
|   The `ContactComponent` _could_ provide it.
 | |
|   But then it would be scoped to this component _only_.
 | |
|   We want to share this service with other contact-related components that we will surely add later.
 | |
| 
 | |
|   In this app we chose to add `ContactService` to the `AppModule` metadata's `providers` list:
 | |
| +makeExample('ngmodule/ts/app/app.module.1b.ts', 'providers', 'app/app.module.ts (providers)')(format=".")
 | |
| :marked
 | |
|   Now `ContactService` (like `UserService`) can be injected into any component in the application.
 | |
| 
 | |
| a#application-scoped-providers
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     ### Application-scoped Providers
 | |
|       The `ContactService` provider is _application_-scoped because Angular
 | |
|       registers a module's `providers` with the application's **root injector**.
 | |
| 
 | |
|       Architecturally, the `ContactService` belongs to the Contact business domain.
 | |
|       Classes in _other_ domains don't need the `ContactService` and shouldn't inject it.
 | |
| 
 | |
|       We might expect Angular to offer a _module_-scoping mechanism to enforce this design.
 | |
|       It doesn't. Angular module instances, unlike components, do not have their own injectors
 | |
|       so they can't have their own provider scopes.
 | |
| 
 | |
|       This omission is intentional.
 | |
|       Angular modules are designed primarily to extend an application,
 | |
|       to enrich the entire app with the module's capabilities.
 | |
| 
 | |
|       Service scoping is rarely a problem in practice.
 | |
|       Non-contact components can't inject the `ContactService` by accident.
 | |
|       To inject `ContactService`, you must first import its _type_.
 | |
|       Only Contact components should import the `ContactService` _type_.
 | |
| 
 | |
|       See the [FAQ that pursues this issue](../cookbook/ngmodule-faq.html#q-component-scoped-providers)
 | |
|       and its mitigations in greater detail.
 | |
| 
 | |
| :marked
 | |
|   ### Run the app
 | |
|   Everything is now in place to run the application with its contact editor.
 | |
| 
 | |
|   The app file structure looks like this:
 | |
| .filetree
 | |
|   .file app
 | |
|   .children
 | |
|     .file app.component.ts
 | |
|     .file app.module.ts
 | |
|     .file highlight.directive.ts
 | |
|     .file main.ts
 | |
|     .file title.component.(html|ts)
 | |
|     .file user.service.ts
 | |
|     .file contact
 | |
|     .children
 | |
|       .file awesome.pipe.ts
 | |
|       .file contact.component.(css|html|ts)
 | |
|       .file contact.service.ts
 | |
|       .file highlight.directive.ts
 | |
| 
 | |
| :marked
 | |
|   Try the example:
 | |
|   <live-example embedded plnkr="contact.1b" img="devguide/ngmodule/contact-1b-plunker.png"></live-example>
 | |
| 
 | |
| a#resolve-conflicts
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Resolve directive conflicts
 | |
| 
 | |
|   We ran into trouble [above](#import-name-conflict) when we declared the contact's `HighlightDirective` because
 | |
|   we already had a `HighlightDirective` class at the application level.
 | |
| 
 | |
|   That both directives have the same name smells of trouble.
 | |
| 
 | |
|   A look at their selectors reveals that they both highlight the attached element with a different color.
 | |
| +makeTabs(
 | |
|   `ngmodule/ts/app/highlight.directive.ts,
 | |
|    ngmodule/ts/app/contact/highlight.directive.ts`,
 | |
|    '',
 | |
|   `app/highlight.directive.ts,
 | |
|    app/contact/highlight.directive.ts`)
 | |
| 
 | |
| :marked
 | |
|   Will Angular use only one of them? No.
 | |
|   Both directives are declared in this module so _both directives are active_.
 | |
| 
 | |
|   When the two directives compete to color the same element,
 | |
|   the directive declared later wins because its DOM changes overwrite the first.
 | |
|   In this case, the contact's `HighlightDirective` colors the application title text blue
 | |
|   when it should stay gold.
 | |
| 
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     The real problem is that there are _two different classes_ trying to do the same thing.
 | |
| 
 | |
|     It's OK to import the _same_ directive class multiple times.
 | |
|     Angular removes duplicate classes and only registers one of them.
 | |
| 
 | |
|     But these are actually two different classes, defined in different files, that happen to have the same name.
 | |
| 
 | |
|     They're not duplicates from Angular's perspective. Angular keeps both directives and
 | |
|     they take turns modifying the same HTML element.
 | |
| 
 | |
| :marked
 | |
|   At least the app still compiles.
 | |
|   If we define two different component classes with the same selector specifying the same element tag,
 | |
|   the compiler reports an error. It can't insert two components in the same DOM location.
 | |
| 
 | |
|   What a mess!
 | |
| 
 | |
|   We can eliminate component and directive conflicts by creating feature modules
 | |
|   that insulate the declarations in one module from the declarations in another.
 | |
| 
 | |
| a#feature-modules
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Feature Modules
 | |
| 
 | |
|   This application isn't big yet. But it's already suffering structural problems.
 | |
| 
 | |
|   * The root `AppModule` grows larger with each new application class and shows no signs of stopping.
 | |
| 
 | |
|   * We have conflicting directives.
 | |
|   The `HighlightDirective` in contact is re-coloring the work done by the `HighlightDirective` declared in `AppModule`.
 | |
|   And it's coloring the application title text when it should only color the `ContactComponent`.
 | |
| 
 | |
|   * The app lacks clear boundaries between contact functionality and other application features.
 | |
|   That lack of clarity makes it harder to assign development responsibilities to different teams.
 | |
| 
 | |
|   We mitigate these problems with _feature modules_.
 | |
| 
 | |
|   ### _Feature Module_
 | |
| 
 | |
|   A _feature module_ is a class adorned by the `@NgModule` decorator and its metadata,
 | |
|   just like a root module.
 | |
|   Feature module metadata have the same properties as the metadata for a root module.
 | |
| 
 | |
|   The root module and the feature module share the same execution context.
 | |
|   They share the same dependency injector which means the services in one module
 | |
|   are available to all.
 | |
| 
 | |
|   There are two significant technical differences:
 | |
| 
 | |
|   1. We _boot_ the root module to _launch_ the app;
 | |
|   we _import_ a feature module to _extend_ the app.
 | |
| 
 | |
|   2. A feature module can expose or hide its implementation from other modules.
 | |
| 
 | |
|   Otherwise, a feature module is distinguished primarily by its intent.
 | |
| 
 | |
|   A feature module delivers a cohesive set of functionality
 | |
|   focused on an application business domain, a user workflow, a facility (forms, http, routing),
 | |
|   or a collection of related utilities.
 | |
| 
 | |
|   While we can do everything within the root module,
 | |
|   feature modules help us partition the app into areas of specific interest and purpose.
 | |
| 
 | |
|   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 chooses to share.
 | |
| 
 | |
|   In the next section, we carve the contact functionality out of the root module
 | |
|   and into a dedicated feature module.
 | |
| 
 | |
|   <a id="contact-module-v1"></a>
 | |
|   ### Make _Contact_ a feature module
 | |
| 
 | |
|   It's easy to refactor the contact material into a contact feature module.
 | |
| 
 | |
|   1. Create the `ContactModule` in the `app/contact` folder.
 | |
|   1. Move the contact material from `AppModule` to `ContactModule`.
 | |
|   1. Replace the imported  `BrowserModule` with `CommonModule`.
 | |
|   1. Import the `ContactModule` into the `AppModule`.
 | |
| 
 | |
|   `AppModule` is the only _existing_ class that changes. But we do add one new file.
 | |
| 
 | |
|   ### Add the _ContactModule_
 | |
| 
 | |
|   Here's the new `ContactModule`
 | |
| +makeExample('ngmodule/ts/app/contact/contact.module.2.ts', '', 'app/contact/contact.module.ts')
 | |
| :marked
 | |
|   We copy from `AppModule` the contact-related import statements and the `@NgModule` properties
 | |
|   that concern the contact and paste them in `ContactModule`.
 | |
| 
 | |
|   We _import_ the `FormsModule` because the contact component needs it.
 | |
| .alert.is-important
 | |
|   :marked
 | |
|     Modules do not inherit access to the components, directives or pipes that are declared in other modules.
 | |
|     What `AppModule` imports is irrelevant to `ContactModule` and vice versa.
 | |
|     Before `ContactComponent` can bind with `[(ngModel)]`, its `ContactModule` must import `FormsModule`.
 | |
| :marked
 | |
|   We also replaced `BrowserModule` by `CommonModule` for reasons explained in
 | |
|   [an FAQ](../cookbook/ngmodule-faq.html#q-browser-vs-common-module).
 | |
| 
 | |
|   We _declare_ the contact component, directive, and pipe in the module `declarations`.
 | |
| 
 | |
|   We _export_ the `ContactComponent` so
 | |
|   other modules that import the `ContactModule` can include it in their component templates.
 | |
| 
 | |
|   All other declared contact classes are private by default.
 | |
|   The `AwesomePipe` and `HighlightDirective` are hidden from the rest of the application.
 | |
|   The `HighlightDirective` can no longer color the `AppComponent` title text.
 | |
| 
 | |
| :marked
 | |
|  ### Refactor the _AppModule_
 | |
|  Return to the `AppModule` and remove everything specific to the contact feature set.
 | |
| 
 | |
|  Delete the contact import statements.
 | |
|  Delete the contact declarations and contact providers.
 | |
|  Remove the `FormsModule` from the `imports` list (`AppComponent` doesn't need it).
 | |
|  Leave only the classes required at the application root level.
 | |
| 
 | |
|  Then import the `ContactModule` so the app can continue to display the exported `ContactComponent`.
 | |
| 
 | |
|  Here's the refactored version of the `AppModule` side-by-side with the previous version.
 | |
| +makeTabs(
 | |
|   `ngmodule/ts/app/app.module.2.ts,
 | |
|    ngmodule/ts/app/app.module.1b.ts`,
 | |
|    '',
 | |
|   `app/app.module.ts (v2),
 | |
|    app/app.module.ts (v1)`)
 | |
| :marked
 | |
|  ### Improvements
 | |
| :marked
 | |
|   There's a lot to like in the revised `AppModule`
 | |
|   * It does not change as the _Contact_ domain grows.
 | |
|   * It only changes when we add new modules.
 | |
|   * It's simpler:
 | |
|     * Fewer import statements
 | |
|     * No `FormsModule` import
 | |
|     * No contact-specific declarations
 | |
|     * No `ContactService` provider
 | |
|     * No `HighlightDirective` conflict
 | |
| 
 | |
|   Try this `ContactModule` version of the sample.
 | |
| 
 | |
|   <live-example embedded plnkr="contact.2" img="devguide/ngmodule/contact-2-plunker.png">Try the live example.</live-example>
 | |
| 
 | |
| a#lazy-load
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Lazy loading modules with the Router
 | |
| 
 | |
|   The Heroic Staffing Agency sample app has evolved.
 | |
|   It has two more modules, one for managing the heroes-on-staff and another for matching crises to the heroes.
 | |
|   Both modules are in the early stages of development.
 | |
|   Their specifics aren't important to the story and we won't discuss every line of code.
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     Examine and download the complete source for this version from the
 | |
|     <live-example plnkr="pre-shared.3" img="devguide/ngmodule/v3-plunker.png">live example.</live-example>
 | |
| :marked
 | |
|   Some facets of the current application merit discussion.
 | |
| 
 | |
|   * The app has three feature modules: Contact, Hero, and Crisis.
 | |
|   * The Angular router helps users navigate among these modules.
 | |
|   * The `ContactComponent` is the default destination when the app starts.
 | |
|   * The `ContactModule` continues to be "eagerly" loaded when the application starts.
 | |
|   * `HeroModule` and the `CrisisModule` are lazy loaded.
 | |
| 
 | |
|   <a id="app-component-template"></a>
 | |
|   Let's start at the top with the new `AppComponent` template:
 | |
|   a title, three links, and a `<router-outlet>`.
 | |
| +makeExample('ngmodule/ts/app/app.component.3.ts', 'template', 'app/app.component.ts (v3 - Template)')(format='.')
 | |
| :marked
 | |
|   The `<app-contact>` element is gone; we're routing to the _Contact_ page now.
 | |
| 
 | |
|   The `AppModule` has changed modestly:
 | |
| +makeExample('ngmodule/ts/app/app.module.3.ts', '', 'app/app.module.ts (v3)')
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     Some file names bear a `.3` extension indicating
 | |
|     a difference with prior or future versions.
 | |
|     We'll explain differences that matter in due course.
 | |
| 
 | |
| :marked
 | |
|   The module still imports `ContactModule` so that its routes and components are mounted when the app starts.
 | |
| 
 | |
|   The module does _not_ import `HeroModule` or `CrisisModule`.
 | |
|   They'll be fetched and mounted asynchronously when the user navigates to one of their routes.
 | |
| 
 | |
|   The significant change from version 2 is the addition of the ***AppRoutingModule*** to the module `imports`.
 | |
|   The `AppRoutingModule` is a [_Routing Module_](../guide/router.html#routing-module)
 | |
|   that handles the app's routing concerns.
 | |
| 
 | |
|   ### App routing
 | |
| +makeExample('ngmodule/ts/app/app-routing.module.ts', '', 'app/app-routing.module.ts')(format='.')
 | |
| :marked
 | |
|   The router is the subject of [its own page](router.html) so we'll skip lightly over the details and
 | |
|   concentrate on the intersection of Angular modules and routing.
 | |
| 
 | |
|   This file defines three routes.
 | |
| 
 | |
|   The first redirects the empty URL (e.g., `http://host.com/`)
 | |
|   to another route whose path is `contact` (e.g., `http://host.com/contact`).
 | |
| 
 | |
|   The `contact` route isn't defined here.
 | |
|   It's defined in the _Contact_ feature's _own_ routing module, `contact-routing.module.ts`.
 | |
|   It's standard practice for feature modules with routing components to define their own routes.
 | |
|   We'll get to that file in a moment.
 | |
| 
 | |
|   The remaining two routes use lazy loading syntax to tell the router where to find the modules:
 | |
| +makeExample('ngmodule/ts/app/app-routing.module.ts', 'lazy-routes')(format='.')
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     A lazy loaded module location is a _string_, not a _type_.
 | |
|     In this app, the string identifies both the module _file_ and the module _class_,
 | |
|     the latter separated from the former by a `#`.
 | |
| 
 | |
| :marked
 | |
|   ### RouterModule.forRoot
 | |
| 
 | |
|   The `forRoot` static class method of the `RouterModule` with the provided configuration,
 | |
|   added to the `imports` array provides the routing concerns for the module.
 | |
| +makeExample('ngmodule/ts/app/app-routing.module.ts', 'forRoot')(format='.')
 | |
| :marked
 | |
|   The returned `AppRoutingModule` class is a `Routing Module` containing both the `RouterModule` directives
 | |
|   and the Dependency Injection providers that produce a configured `Router`.
 | |
| 
 | |
|   This `AppRoutingModule` is intended for the app _root_ module _only_.
 | |
| 
 | |
| .alert.is-critical
 | |
|   :marked
 | |
|     Never call `RouterModule.forRoot` in a feature routing module.
 | |
| :marked
 | |
|   Back in the root `AppModule`, we add the `AppRoutingModule` to its `imports` list,
 | |
|   and the app is ready to navigate.
 | |
| +makeExample('ngmodule/ts/app/app.module.3.ts', 'imports', 'app/app.module.ts (imports)')(format='.')
 | |
| 
 | |
| :marked
 | |
|   ### Routing to a feature module
 | |
|   The `app/contact` folder holds a new file, `contact-routing.module.ts`.
 | |
|   It defines the `contact` route we mentioned a bit earlier and also provides a `ContactRoutingModule` like so:
 | |
| +makeExample('ngmodule/ts/app/contact/contact-routing.module.ts', 'routing', 'app/contact/contact-routing.module.ts (routing)')(format='.')
 | |
| :marked
 | |
|   This time we pass the route list to the `forChild` method of the `RouterModule`.
 | |
|   It's only responsible for providing additional routes and is intended for feature modules.
 | |
| 
 | |
| .alert.is-important
 | |
|   :marked
 | |
|     Always call `RouterModule.forChild` in a feature routing module.
 | |
| 
 | |
| .alert.is-helpful
 | |
|   :marked
 | |
|     **_forRoot_** and **_forChild_** are conventional names for methods that
 | |
|     deliver different `import` values to root and feature modules.
 | |
|     Angular doesn't recognize them but Angular developers do.
 | |
| 
 | |
|     [Follow this convention](../cookbook/ngmodule-faq.html#q-for-root) if you write a similar module
 | |
|     that has both shared [_declarables_](../cookbook/ngmodule-faq.html#q-declarable) and services.
 | |
| 
 | |
| :marked
 | |
|   `ContactModule` has changed in two small but important details
 | |
| +makeTabs(
 | |
|   `ngmodule/ts/app/contact/contact.module.3.ts,
 | |
|    ngmodule/ts/app/contact/contact.module.2.ts`,
 | |
|    'class, class',
 | |
|   `app/contact/contact.module.3.ts,
 | |
|    app/contact/contact.module.2.ts`)
 | |
| :marked
 | |
|   1. It imports the `ContactRoutingModule` object from `contact-routing.module.ts`
 | |
|   1. It no longer exports `ContactComponent`
 | |
| 
 | |
|   Now that we navigate to `ContactComponent` with the router there's no reason to make it public.
 | |
|   Nor does it need a selector.
 | |
|   No template will ever again reference this `ContactComponent`.
 | |
|   It's gone from the [_AppComponent_ template](#app-component-template).
 | |
| 
 | |
| a#hero-module
 | |
| :marked
 | |
|   ### Lazy loaded routing to a module
 | |
| 
 | |
|   The lazy loaded `HeroModule` and `CrisisModule` follow the same principles as any feature module.
 | |
|   They don't look different from the eagerly loaded `ContactModule`.
 | |
| 
 | |
|   The `HeroModule` is a bit more complex than the `CrisisModule` which makes it
 | |
|   a more interesting and useful example. Here's its file structure:
 | |
| 
 | |
| .filetree
 | |
|   .file hero
 | |
|   .children
 | |
|     .file hero-detail.component.ts
 | |
|     .file hero-list.component.ts
 | |
|     .file hero.component.ts
 | |
|     .file hero.module.ts
 | |
|     .file hero-routing.module.ts
 | |
|     .file hero.service.ts
 | |
|     .file highlight.directive.ts
 | |
| :marked
 | |
|   This is the child routing scenario familiar to readers of the [Router](router.html#child-routing-component) page.
 | |
|   The `HeroComponent` is the feature's top component and routing host.
 | |
|   Its template has a `<router-outlet>` that displays either a list of heroes (`HeroList`)
 | |
|   or an editor of a selected hero (`HeroDetail`).
 | |
|   Both components delegate to the `HeroService` to fetch and save data.
 | |
| 
 | |
|   There's yet _another_ `HighlightDirective` that colors elements in yet a different shade.
 | |
|   We should [do something](#shared-module "Shared modules") about the repetition and inconsistencies.
 | |
|   We endure for now.
 | |
| 
 | |
|   The `HeroModule` is a feature module like any other.
 | |
| +makeExample('ngmodule/ts/app/hero/hero.module.3.ts', 'class', 'app/hero/hero.module.ts (class)')(format='.')
 | |
| :marked
 | |
|   It imports the `FormsModule` because the `HeroDetailComponent` template binds with `[(ngModel)]`.
 | |
|   It imports the `HeroRoutingModule` from `hero-routing.module.ts` just as `ContactModule` and `CrisisModule` do.
 | |
| 
 | |
|   The `CrisisModule` is much the same. There's nothing more to say that's new.
 | |
| 
 | |
|   <live-example embedded plnkr="pre-shared.3" img="devguide/ngmodule/v3-plunker.png">Try the live example.</live-example>
 | |
| 
 | |
| a#shared-module
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Shared modules
 | |
| 
 | |
|   The app is shaping up.
 | |
|   One thing we don't like is carrying three different versions of the `HighlightDirective`.
 | |
|   And there's a bunch of other stuff cluttering the app folder level that could be tucked away.
 | |
| 
 | |
|   Let's add a `SharedModule` to hold the common components, directives, and pipes
 | |
|   and share them with the modules that need them.
 | |
| 
 | |
|   * create an `app/shared` folder
 | |
|   * move the `AwesomePipe` and `HighlightDirective` from `app/contact` to `app/shared`.
 | |
|   * delete the `HighlightDirective` classes from `app/` and `app/hero`
 | |
|   * create a `SharedModule` class to own the shared material
 | |
|   * update other feature modules to import `SharedModule`
 | |
| 
 | |
|   Most of this is familiar blocking and tackling. Here is the `SharedModule`
 | |
| +makeExample('ngmodule/ts/app/shared/shared.module.ts', '', 'app/app/shared/shared.module.ts')
 | |
| :marked
 | |
|   Some highlights
 | |
|   * It imports the `CommonModule` because its component needs common directives.
 | |
|   * It declares and exports the utility pipe, directive, and component classes as expected.
 | |
|   * It re-exports the `CommonModule` and `FormsModule`
 | |
| 
 | |
|   ### Re-exporting other modules
 | |
| 
 | |
|   While reviewing our application, we noticed that many components requiring `SharedModule` directives
 | |
|   also use `NgIf` and `NgFor` from `CommonModule`
 | |
|   and bind to component properties with `[(ngModel)]`, a directive in the `FormsModule`.
 | |
|   Modules that declare these components would have to import `CommonModule`, `FormsModule` and `SharedModule`.
 | |
| 
 | |
|   We can reduce the repetition by having `SharedModule` re-export `CommonModule` and `FormsModule`
 | |
|   so that importers of `SharedModule` get `CommonModule` and `FormsModule` _for free_.
 | |
| 
 | |
|   As it happens, the components declared by `SharedModule` itself don't bind with `[(ngModel)]`.
 | |
|   Technically,  there is no need for `SharedModule` to import `FormsModule`.
 | |
| 
 | |
|   `SharedModule` can still export `FormsModule` without listing it among its `imports`.
 | |
| 
 | |
|   ### Why _TitleComponent_ isn't shared
 | |
| 
 | |
|   `SharedModule` exists to make commonly used components, directives and pipes available
 | |
|   for use in the templates of components in _many_ other modules.
 | |
| 
 | |
|   The `TitleComponent` is used _only once_ by the `AppComponent`.
 | |
|   There's no point in sharing it.
 | |
| 
 | |
|   <a id="no-shared-module-providers"></a>
 | |
|   ### Why _UserService_ isn't shared
 | |
| 
 | |
|   While many components share the same service _instances_,
 | |
|   they rely on Angular dependency injection to do this kind of sharing, not the module system.
 | |
| 
 | |
|   Several components of our sample inject the `UserService`.
 | |
|   There should be _only one_ instance of the `UserService` in the entire application
 | |
|   and _only one_ provider of it.
 | |
| 
 | |
|   `UserService` is an application-wide singleton.
 | |
|   We don't want each module to have its own separate instance.
 | |
|   Yet there is [a real danger](../cookbook/ngmodule-faq.html#q-why-it-is-bad) of that happening
 | |
|   if the `SharedModule` provides the `UserService`.
 | |
| 
 | |
| .alert.is-critical
 | |
|   :marked
 | |
|     Do **not** specify app-wide singleton `providers` in a shared module.
 | |
|     A lazy loaded module that imports that shared module will make its own copy of the service.
 | |
| 
 | |
| a#core-module
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## The Core module
 | |
|   At the moment, our root folder is cluttered with the `UserService`
 | |
|   and the `TitleComponent` that only appears in the root `AppComponent`.
 | |
|   We did not include them in the `SharedModule` for reasons just explained.
 | |
| 
 | |
|   Instead, we'll gather them in a single `CoreModule` that we **import _once_ when the app starts**
 | |
|   and _never import anywhere else_.
 | |
| 
 | |
|   **Steps:**
 | |
| 
 | |
|   * create an `app/core` folder
 | |
|   * move the `UserService` and `TitleComponent` from `app/` to `app/core`
 | |
|   * create a `CoreModule` class to own the core material
 | |
|   * update the `AppRoot` module to  import `CoreModule`
 | |
| 
 | |
|   Again, most of this is familiar blocking and tackling. The interesting part is the `CoreModule`
 | |
| +makeExample('ngmodule/ts/app/core/core.module.ts', 'v4', 'app/app/core/core.module.ts')
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     We're importing some extra symbols from the Angular core library that we're not using yet.
 | |
|     They'll become relevant later in this page.
 | |
| :marked
 | |
|   The `@NgModule` metadata should be familiar.
 | |
|   We declare the `TitleComponent`  because this module _owns_ it and we export it
 | |
|   because `AppComponent` (which is in `AppModule`) displays the title in its template.
 | |
|   `TitleComponent` needs the Angular `NgIf` directive that we import from `CommonModule`.
 | |
| 
 | |
|   `CoreModule` _provides_ the `UserService`. Angular registers that provider with the app root injector,
 | |
|   making a singleton instance of the `UserService` available to any component that needs it,
 | |
|   whether that component is eagerly or lazily loaded.
 | |
| 
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     ### Why bother?
 | |
|     This scenario is clearly contrived.
 | |
|     The app is too small to worry about a single service file and a tiny, one-time component.
 | |
| 
 | |
|     A `TitleComponent` sitting in the root folder isn't bothering anyone.
 | |
|     The root `AppModule` can register the `UserService` itself,
 | |
|     as it does currently, even if we decide to relocate the `UserService` file to the `app/core` folder.
 | |
| 
 | |
|     Real world apps have more to worry about.
 | |
|     They can have several single-use components (e.g., spinners, message toasts, and modal dialogs)
 | |
|     that appear only in the `AppComponent` template.
 | |
|     We don't import them elsewhere so they're not _shared_ in that sense.
 | |
|     Yet they're too big and messy to leave loose in the root folder.
 | |
| 
 | |
|     Apps often have many singleton services like this sample's `UserService`.
 | |
|     Each must be registered _exactly once_, in the app root injector, when the application starts.
 | |
| 
 | |
|     While many Components inject such services in their constructors —
 | |
|     and therefore require JavaScript `import` statements to import their symbols —
 | |
|     no other component or module should define or re-create the services themselves.
 | |
|     Their _providers_ are not shared.
 | |
| 
 | |
|     We recommend collecting such single-use classes and hiding their gory details inside a `CoreModule`.
 | |
|     A simplified root `AppModule` imports `CoreModule` in its capacity as orchestrator of the application as a whole.
 | |
| 
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Cleanup
 | |
|   Having refactored to a `CoreModule` and a `SharedModule`, it's time to cleanup the other modules.
 | |
| 
 | |
|   ### A trimmer _AppModule_
 | |
| 
 | |
|   Here is the updated `AppModule` paired with version 3 for comparison:
 | |
| +makeTabs(
 | |
|   `ngmodule/ts/app/app.module.ts,
 | |
|    ngmodule/ts/app/app.module.3.ts`,
 | |
|    'v4,',
 | |
|   `app/app.module.ts (v4),
 | |
|    app/app.module.ts (v3)`)
 | |
| 
 | |
| :marked
 | |
|   Notice that `AppModule` is ...
 | |
|   * a little smaller because many `app/root` classes have moved to other modules.
 | |
|   * stable because we'll add future components and providers to other modules, not this one.
 | |
|   * delegating to imported modules rather than doing work.
 | |
|   * focused on its main task, orchestrating the app as a whole.
 | |
| 
 | |
|   ### A trimmer _ContactModule_
 | |
|   Here is the new `ContactModule` paired with the prior version:
 | |
| +makeTabs(
 | |
|   `ngmodule/ts/app/contact/contact.module.ts,
 | |
|    ngmodule/ts/app/contact/contact.module.3.ts`,
 | |
|    '',
 | |
|   `app/contact/contact.module.ts (v4),
 | |
|    app/contact/contact.module.ts (v3)`)
 | |
| 
 | |
| :marked
 | |
|   Notice that
 | |
|   * The `AwesomePipe` and `HighlightDirective` are gone.
 | |
|   * The imports include `SharedModule` instead of `CommonModule` and `FormsModule`
 | |
|   * This new version is leaner and cleaner.
 | |
| 
 | |
| .l-hr
 | |
| 
 | |
| a#core-for-root
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Configure core services with _CoreModule.forRoot_
 | |
| 
 | |
|   A module that adds providers to the application can offer a facility for configuring those providers as well.
 | |
| 
 | |
|   By convention, the **_forRoot_** static method both provides and configures services at the same time.
 | |
|   It takes a service configuration object and returns a
 | |
|   [ModuleWithProviders](../api/core/index/ModuleWithProviders-interface.html) which is
 | |
|   a simple object with two properties:
 | |
|   * `ngModule` - the `CoreModule` class
 | |
|   * `providers` - the configured providers
 | |
| 
 | |
|   The root `AppModule` imports the `CoreModule` and adds the `providers` to the `AppModule` providers.
 | |
| .l-sub-section
 | |
|   :marked
 | |
|     More precisely, Angular accumulates all imported providers _before_ appending the items listed in `@NgModule.providers`.
 | |
|     This sequence ensures that whatever we add explicitly to the `AppModule` providers takes precedence
 | |
|     over the providers of imported modules.
 | |
| :marked
 | |
|   Let's add a `CoreModule.forRoot` method that configures the core `UserService`.
 | |
| 
 | |
|   We've extended the core `UserService` with an optional, injected `UserServiceConfig`.
 | |
|   If a `UserServiceConfig` exists, the `UserService` sets the user name from that config.
 | |
| +makeExample('ngmodule/ts/app/core/user.service.ts', 'ctor', 'app/core/user.service.ts (constructor)')(format='.')
 | |
| :marked
 | |
|   Here's `CoreModule.forRoot` that takes a `UserServiceConfig` object:
 | |
| +makeExample('ngmodule/ts/app/core/core.module.ts', 'for-root', 'app/core/core.module.ts (forRoot)')(format='.')
 | |
| :marked
 | |
|   Lastly, we call it _within the_ `imports` _list_ of the `AppModule`.
 | |
| +makeExample('ngmodule/ts/app/app.module.ts', 'import-for-root', 'app//app.module.ts (imports)')(format='.')
 | |
| :marked
 | |
|   The app displays "Miss Marple" as the user instead of the default "Sherlock Holmes".
 | |
| 
 | |
| .alert.is-important
 | |
|   :marked
 | |
|     Call `forRoot` only in the root application module, `AppModule`.
 | |
|     Calling it in any other module, particularly in a lazy loaded module,
 | |
|     is contrary to the intent and is likely to produce a runtime error.
 | |
| 
 | |
|     Remember to _import_ the result; don't add it to any other `@NgModule` list.
 | |
| 
 | |
| .l-hr
 | |
| 
 | |
| a#prevent-reimport
 | |
| .l-main-section
 | |
| :marked
 | |
|   ## Prevent reimport of the _CoreModule_
 | |
| 
 | |
|   Only the root `AppModule` should import the `CoreModule`.
 | |
|   [Bad things happen](../cookbook/ngmodule-faq.html#q-why-it-is-bad) if a lazy loaded module imports it.
 | |
| 
 | |
|   We could _hope_ that no developer makes that mistake.
 | |
|   Or we can guard against it and fail fast by adding the following `CoreModule` constructor.
 | |
| +makeExample('ngmodule/ts/app/core/core.module.ts', 'ctor')(format='.')
 | |
| :marked
 | |
|   The constructor tells Angular to inject the `CoreModule` into itself.
 | |
|   That seems dangerously circular.
 | |
| 
 | |
|   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 is no ancestor injector that could provide an instance of `CoreModule`.
 | |
|   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 we improperly import `CoreModule` into a lazy loaded module such as `HeroModule` (try it).
 | |
| 
 | |
|   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.
 | |
| :marked
 | |
|   ### Conclusion
 | |
| 
 | |
|   You made it! You can examine and download the complete source for this final version from the live example.
 | |
|   <live-example embedded  img="devguide/ngmodule/final-plunker.png"></live-example>
 | |
| 
 | |
|   ### Frequently Asked Questions
 | |
| 
 | |
|   Now that you understand Angular Modules, you may be interested
 | |
|   in the companion [Angular Module FAQs](../cookbook/ngmodule-faq.html "Angular Module FAQs") cookbook
 | |
|   with its ready answers to specific design and implementation questions.
 |