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.
 |