| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | block includes | 
					
						
							|  |  |  |   include ../_util-fns | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TODO | 
					
						
							|  |  |  |   Images | 
					
						
							|  |  |  |   Confirm plunkers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   **Angular Modules** help organize an application into cohesive blocks of functionality. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   An Angular Module _class_ is adorned with the **NgModule** decorator that defines metadata about the module.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This chapter explains how to **create** `NgModule` classes and how to load them,  | 
					
						
							|  |  |  |   either immediately when the application launches or later, as needed, via the Router.   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ## 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 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * [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") | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   * [NgModule metadata properties](#ngmodule-properties "A technical summary of the @NgModule metadata properties") | 
					
						
							|  |  |  |   * [FAQ](#faq "Frequently asked questions") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   ### Live examples | 
					
						
							|  |  |  |   This chapter 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> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 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 together_. | 
					
						
							|  |  |  |   * make some of those classes public so that other component templates can use them. | 
					
						
							|  |  |  |   * hide other classes as implementation details. | 
					
						
							|  |  |  |   * import other modules with the components, directives and pipes it needs. | 
					
						
							|  |  |  |   * 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 chapter. 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 | 
					
						
							| 
									
										
										
										
											2016-08-10 10:00:08 +08:00
										 |  |  |   The `@NgModule` decorator defines the metadata for the module.  | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   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 chapter 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](#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 chapter demonstrate the dynamic bootstrapping approach.  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 19:44:22 +02:00
										 |  |  |   <live-example embedded plnkr="minimal.0">Try the live example.</live-example> | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |    | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ### 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 report an error in the console because | 
					
						
							|  |  |  |   it doesn't recognize the `highlight` binding.  | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   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) chapter 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_ it. | 
					
						
							|  |  |  |     We'll cover re-exporting a module [later](#q-re-export) in the chapter. | 
					
						
							|  |  |  |     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.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 works and the user input is validated by Angular Forms. | 
					
						
							|  |  |  | .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_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       [An FAQ below](#q-component-scoped-providers) pursues this issue 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 | 
					
						
							|  |  |  |   <live-example plnkr="contact.1b">Try the live example.</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`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   * A change to a contact class could break an application part in some unrelated section of the app. | 
					
						
							|  |  |  |   The app is brittle and hard to test.   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   * 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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   <a id="contact-module-v1"></a> | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   ### 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. | 
					
						
							|  |  |  |     The fact that `AppModule` imports `FormsModule` is irrelevant. | 
					
						
							|  |  |  |     The `ContactModule` must import `FormsModule` explicitly so that | 
					
						
							|  |  |  |     `ContactComponent` can data bind with `ngModel`. | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   We also replaced `BrowserModule` by `CommonModule` for reasons explained [below](#q-browser-vs-common-module). | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 19:44:22 +02:00
										 |  |  |   <live-example embedded plnkr="contact.2">Try the live example.</live-example> | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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">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 a ***routing*** object to the `imports`. | 
					
						
							|  |  |  |   The routing object, which provides a configured `Router` service, is defined in the `app.routing.ts` file. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ### App routing | 
					
						
							|  |  |  | +makeExample('ngmodule/ts/app/app.routing.ts', '', 'app/app.routing.ts')(format='.') | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The router is the subject of [its own chapter](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 file, `contact.routing.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.ts', 'lazy-routes')(format='.') | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Note that the module location is a _string_, not a _type_.  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     To reference the _type_ we'd have to import the module, which loads the module immediately, | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |     defeating our intent to load the module later.  | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     A string, on the other hand, is just a string. It has no side-effects. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | :marked | 
					
						
							|  |  |  |   The module location strings in this app identify module _files_, not module _classes_. | 
					
						
							|  |  |  |   That works because each module class is marked as the default export in its file. | 
					
						
							|  |  |  | +makeExample('ngmodule/ts/app/crisis/crisis.module.ts', 'export-default', '/app/crisis/crisis.module.ts (export default)')(format='.') | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |     _Remember to use_ `export default`_, not just_ `export`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### RouterModule.forRoot | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The last line calls the `forRoot` static class method of the `RouterModule`, passing in the configuration. | 
					
						
							|  |  |  | +makeExample('ngmodule/ts/app/app.routing.ts', 'forRoot')(format='.') | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The returned `routing` object is a `ModuleWithProviders` containing both the `RouterModule` directives | 
					
						
							|  |  |  |   and the Dependency Injection providers that produce a configured `Router`.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This `routing` object is intended for the app _root_ module _only_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .alert.is-critical | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Never call `RouterModule.forRoot` in a feature module. | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Back in the root `AppModule`, we add this `routing` object 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.ts`. | 
					
						
							|  |  |  |   It defines the `contact` route we mentioned a bit earlier and also creates a `routing` object like so: | 
					
						
							|  |  |  | +makeExample('ngmodule/ts/app/contact/contact.routing.ts', 'routing', 'app/contact/contact.routing.ts (routing)')(format='.') | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   This time we pass the route list to the `forChild` method of the `RouterModule`. | 
					
						
							|  |  |  |   It produces a different kind of object intended for feature modules. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .alert.is-important | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Always call `RouterModule.forChild` in a feature 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. | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     [Follow this convention](#q-for-root) if you write a similar module | 
					
						
							|  |  |  |     that has both shared [_declarables_](#q-declarable) and services. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | :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 `routing` object from `contact.routing.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.ts | 
					
						
							|  |  |  |     .file hero.service.ts | 
					
						
							|  |  |  |     .file highlight.directive.ts | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   This is the child routing scenario familiar to readers of [Router](router.html#child-routing-component) chapter. | 
					
						
							|  |  |  |   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)]`.  | 
					
						
							| 
									
										
										
										
											2016-08-19 01:44:00 +02:00
										 |  |  |   It imports a `routing` object from `hero.routing.ts` just as `ContactModule` and `CrisisModule` do. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   The `CrisisModule` is much the same. There's nothing more to say that's new.  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-25 19:44:22 +02:00
										 |  |  |   <live-example embedded plnkr="pre-shared.3">Try the live example.</live-example> | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Let's add a `SharedModule` to hold the common components, directives, and pipes  | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   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 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * update other feature modules to import `SharedModule` | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Most of this is familiar blocking and tackling. Here is the `SharedModule` | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | +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. | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * 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`. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   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 importing it. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   ### Why _TitleComponent_ isn't shared | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   `SharedModule` exists to make commonly used components, directives and pipes available | 
					
						
							|  |  |  |   for use in the templates of components in _many_ other modules. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   The `TitleComponent` is used _only once_ by the `AppComponent`.  | 
					
						
							|  |  |  |   There's no point in sharing it. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   <a id="no-shared-module-providers"></a> | 
					
						
							|  |  |  |   ### Why _UserService_ isn't shared   | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   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. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   `UserService` is an application-wide singleton. | 
					
						
							|  |  |  |   We don't want each module to have its own separate instance.  | 
					
						
							|  |  |  |   Yet there is [a real danger](#q-why-it-is-bad) of that happening  | 
					
						
							|  |  |  |   if the `SharedModule` provides the `UserService`. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | .alert.is-critical | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     Do **not** specify singleton `providers` in shared modules. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | a#core-module | 
					
						
							|  |  |  | .l-main-section | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   ## 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. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Instead, we'll gather them in a single `CoreModule` that we **import _once_ when the app starts** | 
					
						
							|  |  |  |   and _never import anywhere else_. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   **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 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     We're importing some extra symbols from the Angular core library that we're not using yet. | 
					
						
							|  |  |  |     They'll become relevant later in this chapter. | 
					
						
							|  |  |  | :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. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     #### 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. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     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. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     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. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     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. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   ## Cleanup | 
					
						
							|  |  |  |   Having refactored to a `CoreModule` and a `SharedModule`, it's time to cleanup the other modules.  | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ### A trimmer _AppModule_ | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   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`, | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |    'v4,', | 
					
						
							|  |  |  |   `app/app.module.ts (v4), | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |    app/app.module.ts (v3)`) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   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. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ### A trimmer _ContactModule_ | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Here is the new `ContactModule` paired with the prior version: | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | +makeTabs( | 
					
						
							|  |  |  |   `ngmodule/ts/app/contact/contact.module.ts, | 
					
						
							|  |  |  |    ngmodule/ts/app/contact/contact.module.3.ts`, | 
					
						
							|  |  |  |    '', | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   `app/contact/contact.module.ts (v4), | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |    app/contact/contact.module.ts (v3)`) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Notice that | 
					
						
							|  |  |  |   * The `AwesomePipe` and `HighlightDirective` are gone. | 
					
						
							|  |  |  |   * The imports include `SharedModule` instead of `CommonModule` and `FormsModule` | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * This new version is leaner and cleaner. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | 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](#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 | 
					
						
							|  |  |  |   We're done with the tutorial portion of the chapter.  | 
					
						
							|  |  |  |   You can examine and download the complete source for this final version from the <live-example>live example.</live-example> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The next section summarizes the `NgModule` API.  | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | a#ngmodule-properties   | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## *NgModule* properties | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The following chart summarizes the `NgModule` metadata properties. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  |   export interface NgModuleMetadataType { | 
					
						
							|  |  |  |     providers?: any[]; | 
					
						
							|  |  |  |     declarations?: Array<Type|any[]>; | 
					
						
							|  |  |  |     imports?: Array<Type|ModuleWithProviders|any[]>; | 
					
						
							|  |  |  |     exports?: Array<Type|any[]>; | 
					
						
							|  |  |  |     entryComponents?: Array<Type|any[]>; | 
					
						
							|  |  |  |     bootstrap?: Array<Type|any[]>; | 
					
						
							|  |  |  |     schemas?: Array<SchemaMetadata|any[]>; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | table | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     th Property | 
					
						
							|  |  |  |     th Description | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top") <code>declarations</code> | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |         A list of [declarable](#q-declarables) classes,  | 
					
						
							|  |  |  |         the **component**, **directive** and **pipe** classes that _belong to this module_. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         These declared classes are visible within the module but invisible to | 
					
						
							|  |  |  |         components in a different module unless (a) they are _exported_ from this module and  | 
					
						
							|  |  |  |         (b) that other module _imports_ this one. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Components, directives and pipes must belong to _exactly_ one module. | 
					
						
							|  |  |  |         The compiler emits an error if we try to declare the same class in more than one module. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         **Do not re-declare a class imported from another module.** | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top") <code>providers</code> | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							|  |  |  |         A list of dependency injection providers. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         Angular registers these providers with the root injector of the module's execution context. | 
					
						
							|  |  |  |         That's the application's root injector for all modules loaded when the application starts. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Angular can inject one of these provider services into any component in the application. | 
					
						
							|  |  |  |         If this module provides the `HeroService`, or any module loaded at launch provides the `HeroService`, | 
					
						
							|  |  |  |         Angular can inject the same `HeroService` intance into any app component. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         A lazy loaded module has its own sub-root injector which typically  | 
					
						
							|  |  |  |         is a direct child of the application root injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Lazy loaded services are scoped to the lazy module's injector. | 
					
						
							|  |  |  |         If a lazy loaded module also provides the `HeroService`,  | 
					
						
							|  |  |  |         any component created within that module's context (e.g., by router navigation) | 
					
						
							|  |  |  |         gets the local instance of the service, not the instance in the root application injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Components in external modules continue to receive the instance created for the application root.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top") <code>imports</code> | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							|  |  |  |         A list of supporting modules. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         Specifically, the list of modules whose exported components, directives or pipes  | 
					
						
							|  |  |  |         are referenced by the component templates declared in this module. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         A component template can [reference](#q-template-reference) another component, directive or pipe | 
					
						
							|  |  |  |         on two conditions: either the referenced class is declared in this module | 
					
						
							|  |  |  |         or the class was imported from another module.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         A component can use the `NgIf` and `NgFor` directives only because its parent module  | 
					
						
							|  |  |  |         imported the Angular `CommonModule` (perhaps indirectly by importing `BrowserModule`). | 
					
						
							|  |  |  |         | 
					
						
							|  |  |  |         We can import many standard directives with the `CommonModule`. | 
					
						
							|  |  |  |         But some familiar directives belong to other modules. | 
					
						
							|  |  |  |         A component template can bind with `[(ngModel)]` only after importing the Angular `FormsModule`. | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top") <code>exports</code> | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							|  |  |  |         A list of declarations — **component**, **directive**, and **pipe** classes — that  | 
					
						
							|  |  |  |         an importing module can use. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Exported declarations are the module's _public API_.  | 
					
						
							|  |  |  |         A component in another module can [reference](#q-template-reference) _this_ module's `HeroComponent`  | 
					
						
							|  |  |  |         if (a) it imports this module and (b) this module exports `HeroComponent`. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         Declarations are private by default. | 
					
						
							|  |  |  |         If this module does _not_ export `HeroComponent`, no other module can see it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Importing a module does _not_ automatically re-export the imported module's exports. | 
					
						
							|  |  |  |         Module 'B' can't use `ngIf` just because it imported module `A` which imported `CommonModule`. | 
					
						
							|  |  |  |         Module 'B' must import `CommonModule` itself. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         A module can list another module among its `exports` in which case | 
					
						
							|  |  |  |         all of that module's public components, directives, and pipes are exported. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         [Re-export](#q-re-export) makes module transitivity explicit. | 
					
						
							|  |  |  |         If Module 'A' re-exports `CommonModule` and Module 'B' imports Module 'A', | 
					
						
							|  |  |  |         Module 'B' components can use `ngIf` even though 'B' itself didn't import `CommonModule`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top") <code>bootstrap</code> | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							|  |  |  |         A list of components that can be [bootstrapped](#bootstrap). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Usually there is only one component in this list, the _root component_ of the application. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         Angular can launch with multiple bootstrap components,  | 
					
						
							|  |  |  |         each with its own location in the host web page. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         A bootstrap component is automatically an `entryComponent`  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top") <code>entryComponents</code> | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							|  |  |  |         A list of components that are _not_ [referenced](#q-template-reference) in a reachable component template. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Most developers will never set this property. Here's why. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         The [_Angular Compiler_](#q-angular-compiler) must know about every component actually used in the application. | 
					
						
							|  |  |  |         The compiler can discover most components by walking the tree of references  | 
					
						
							|  |  |  |         from one component template to another. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         But there's always at least one component that is not referenced in any template: | 
					
						
							|  |  |  |         the root component, `AppComponent`, that we bootstrap to launch the app. | 
					
						
							|  |  |  |         That's why it's called an _entry component_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Routed components are also _entry components_ because they aren't referenced in a template either. | 
					
						
							|  |  |  |         The router creates them and drops them into the DOM near a `<router-outlet>`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         While the bootstrapped and routed components are _entry components_,  | 
					
						
							|  |  |  |         we usally don't have to add them to a module's `entryComponents` list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Angular automatically adds components in the module's `bootstrap` list to the `entryComponents` list. | 
					
						
							|  |  |  |         The `RouterModule` adds routed components to that list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         That leaves only two sources of undiscoverable components. | 
					
						
							|  |  |  |         1. Components bootstrapped using one of the imperative techniques. | 
					
						
							|  |  |  |         1. Components dynamically loaded into the DOM by some means other than the router. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         Both are advanced techniques that few developers will ever employ.  | 
					
						
							|  |  |  |         If you are one of those few, you'll have to add these components to the  | 
					
						
							|  |  |  |         `entryComponents` list yourself, either programmatically or by hand. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#faq  | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## FAQ: Frequently Asked Questions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Declarations | 
					
						
							|  |  |  |   * [What classes should I add to _declarations_?](#q-what-to-declare) | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * [What is a _declarable_?](#q-declarable) | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   * [What classes should I *not* add to _declarations_?](#q-what-not-to-declare) | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * [Why list the same component in multiple _NgModule_ properties?](#q-why-multiple-mentions) | 
					
						
							|  |  |  |   * [What does "_Can't bind to 'x' since it isn't a known property of 'y'_" mean?](#q-why-cant-bind-to) | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Imports | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   * [What should I import?](#q-what-to-import) | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * [Should I import _BrowserModule_ or _CommonModule_?](#q-browser-vs-common-module) | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   * [What if I import the same module twice?](#q-reimport) | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Exports   | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   * [What should I export?](#q-what-to-export) | 
					
						
							|  |  |  |   * [What should I *not* export?](#q-what-not-to-export) | 
					
						
							|  |  |  |   * [Can I re-export imported classes and modules?](#q-re-export) | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * [What is the _forRoot_ method?](#q-for-root) | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Service Providers   | 
					
						
							|  |  |  |   * [Why is a service provided in a feature module visible everywhere?](#q-module-provider-visibility) | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * [Why is a service provided in a _lazy loaded_ module visible only to that module?](#q-lazy-loaded-module-provider-visibility)  | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   * [What if two modules provide the _same_ service?](#q-module-provider-duplicates) | 
					
						
							|  |  |  |   * [How do I restrict service scope to a module?](#q-component-scoped-providers) | 
					
						
							|  |  |  |   * [Should I add providers to the root _AppModule_ or the root _AppComponent_?](#q-root-component-or-module) | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * [Why is it bad if _SharedModule_ provides a service to a lazy loaded module?](#q-why-it-is-bad) | 
					
						
							|  |  |  |   * [Why does lazy loading create a child injector?](#q-why-child-injector)   | 
					
						
							|  |  |  |   * [How can I tell if a module or service was previously loaded?](#q-is-it-loaded) | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Entry Components | 
					
						
							|  |  |  |   * [What is an _entry component_?](#q-entry-component-defined) | 
					
						
							|  |  |  |   * [What is the difference between a _bootstrap_ component and an _entry component_?](#q-bootstrap_vs_entry_component) | 
					
						
							|  |  |  |   * [When do I add components to _entryComponents_?](#q-when-entry-components) | 
					
						
							|  |  |  |   * [Why does Angular need _entryComponents_?](#q-why-entry-components) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   General | 
					
						
							|  |  |  |   * [What kinds of modules should I have and how should I use them?](#q-module-recommendations) | 
					
						
							|  |  |  |   * [What's the difference between Angular and JavaScript Modules?](#q-ng-vs-js-modules) | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   * [What is a "template reference"?](#q-template-reference) | 
					
						
							|  |  |  |   * [How does Angular find components, directives, and pipes in a template?](#q-template-reference)   | 
					
						
							|  |  |  |   * [What is the Angular Compiler?](#q-angular-compiler)   | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-what-to-declare | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What classes should I add to _declarations_? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Add [declarable](#q-declarable) classes — components, directives, and pipes — to a `declarations` list. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   These classes must be declared in _exactly one_ module of the application. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   Declare them in _this_ module if they _belong_ to this module. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | a#q-declarable | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What is a _declarable_? | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   _Declarables_ are the class types — components, directives, and pipes — | 
					
						
							|  |  |  |   that you can add to a module's `declarations` list.  | 
					
						
							|  |  |  |   They're the _only_ classes that you can add to `declarations`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | a#q-what-not-to-declare | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What classes should I _not_ add to _declarations_? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Only [declarable](#q-declarable) classes can be added to a module's `declarations` list. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   Do *not* declare  | 
					
						
							|  |  |  |   * a class that is already declared in another module, whether an app module, @angular module, or 3rd party module | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   * an array of directives imported from another module.  | 
					
						
							|  |  |  |   For example, do not declare FORMS_DIRECTIVES from `@angular/forms`. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * module classes | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   * service classes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   * non-Angular classes and objects such as  | 
					
						
							|  |  |  |   strings, numbers, functions, entity models, configurations, business logic, and helper classes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-why-multiple-mentions | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   ### Why list the same component in multiple _NgModule_ properties? | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   We often see `AppComponent` listed in both `declarations` and `bootstrap`. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   We might see `HeroComponent` listed in `declarations`, `exports`, and `entryComponents`. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   That _feels_ redundant but these properties have different functions  | 
					
						
							|  |  |  |   and we can't infer that membership in one list implies membership in another list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   * `AppComponent` could be declared in this module but not bootstrapped. | 
					
						
							|  |  |  |   * `AppComponent` could be bootstrapped in this module but declared in a different feature module. | 
					
						
							|  |  |  |   * `HeroComponent` could be imported from another app module (so we can't declare it) and re-exported by this module. | 
					
						
							|  |  |  |   * `HeroComponent` could be exported for inclusion in an external component's template and also dynamically loaded in a pop-up dialog. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-why-cant-bind-to | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What does "_Can't bind to 'x' since it isn't a known property of 'y'_" mean? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This error usually means either that you neglected to declare the directive "x"  | 
					
						
							|  |  |  |   or you haven't imported the module to which "x" belongs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   For example, if "x" is `ngModel`, you probably haven't imported the `FormsModule` from `@angular/forms`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Perhaps you declared "x" in an application sub-module but forgot to export it?  | 
					
						
							|  |  |  |   The "x" class won't be visible to other modules until you add it to the `exports` list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-what-to-import | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What should I import? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Import modules whose public (exported) [declarable classes](#q-declarable)  | 
					
						
							|  |  |  |   you need to reference in this module's component templates. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This invariably means importing `CommonModule` from `@angular/common` for access to | 
					
						
							|  |  |  |   the Angular directives such as `NgIf` and `NgFor`.  | 
					
						
							|  |  |  |   You can import it directly or from another module that [re-exports](#q-reexport) it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Import `FormsModule` from `@angular/forms`  | 
					
						
							|  |  |  |   if your components have `[(ngModel)]` two-way binding expressions. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Import _shared_ and _feature_ modules when this module's components incorporate their | 
					
						
							|  |  |  |   components, directives, and pipes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Only [import _BrowserModule_](#q-browser-vs-common-module) in the root `AppModule`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-browser-vs-common-module | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Should I import _BrowserModule_ or _CommonModule_? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   The **root application module** (`AppModule`) of almost every browser application | 
					
						
							|  |  |  |   should import `BrowserModule` from `@angular/core`. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   `BrowserModule` provides services that are essential to launch and run a browser app. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   `BrowserModule` also re-exports `CommonModule` from `@angular/common` | 
					
						
							|  |  |  |   which means that component in the `AppModule` module also have access to | 
					
						
							|  |  |  |   the Angular directives every app needs such as `NgIf` and `NgFor`. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   _Do not import_ `BrowserModule` in any other module. | 
					
						
							|  |  |  |   *Feature modules* and *lazy loaded modules* should import `CommonModule` instead. | 
					
						
							|  |  |  |   They need the common directives. They don't need to re-install the app-wide providers.  | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     `BrowserModule` throws an error if you try to lazy load  a module that imports it. | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   Importing `CommonModule` also frees feature modules for use on _any_ target platform, not just browsers, | 
					
						
							|  |  |  |   a fact of some interest to authors of cross-platform libraries. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr  | 
					
						
							|  |  |  | a#q-reimport | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What if I import the same module twice? | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   That's not a problem. When three modules all import Module 'A',  | 
					
						
							|  |  |  |   Angular evaluates Module 'A' once, the first time it encounters it, and does not do so again.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   That's true at whatever level `A` appears in a hierarchy of imported modules. | 
					
						
							|  |  |  |   When Module 'B' imports Module 'A', Module 'C' imports 'B', and Module 'D' imports `[C, B, A]`, | 
					
						
							|  |  |  |   then 'D' triggers the evaluation of 'C' which triggers the evaluation of 'B' which evaluates 'A'. | 
					
						
							|  |  |  |   When Angular gets to the 'B' and 'A' in 'D', they're already cached and ready to go. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Angular does not like modules with circular references so don't let Module 'A' import Module 'B' which imports Module 'A'. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr  | 
					
						
							|  |  |  | a#q-what-to-export | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What should I export? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Export [declarable](#q-declarable) classes that components in _other_ modules | 
					
						
							|  |  |  |   should be able to reference in their templates. These are your _public_ classes. | 
					
						
							|  |  |  |   If you don't export a class, it stays _private_, visible only to other component | 
					
						
							|  |  |  |   declared in this module. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   You _can_ export any declarable class — components, directives, and pipes —  | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   whether it is declared in this module or in an imported module. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   You _can_ re-export entire imported modules which effectively re-exports all of their exported classes. | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   A module can even export a module that it doesn't import.  | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-what-not-to-export | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What should I *not* export? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Do *not* export | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * Private components, directives, and pipes that you need only within components declared in this module. | 
					
						
							|  |  |  |   If you don't want another module to see it, don't export it. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * Non-declarable objects such as services, functions, configurations, entity models, etc. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * Components that are only loaded dynamically by the router or by bootstrapping. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   Such [entry components](#q-entry-component-defined) can never be selected in another component's template. | 
					
						
							|  |  |  |   There's no harm in exporting them but no benefit either.  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   * Pure service modules that don't have public (exported) declarations.  | 
					
						
							|  |  |  |   For example, there is no point in re-exporting `HttpModule` because it doesn't export anything. | 
					
						
							|  |  |  |   It's only purpose is to add http service providers to the application as a whole. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-reexport | 
					
						
							|  |  |  | a#q-re-export | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Can I re-export classes and modules? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Absolutely! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Modules are a great way to selectively aggregate classes from other modules and | 
					
						
							|  |  |  |   re-export them in a consolidated, convenience module. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   A module can re-export entire modules which effectively re-exports all of their exported classes. | 
					
						
							|  |  |  |   Angular's own `BrowserModule` exports a couple of modules like this: | 
					
						
							|  |  |  | code-example. | 
					
						
							|  |  |  |   exports: [CommonModule, ApplicationModule] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   A module can export a combination of its own declarations, selected imported classes, and imported modules. | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Don't bother re-exporting pure service modules. | 
					
						
							|  |  |  |     Pure service modules don't export [declarable](#q-declarable) classes that another module could use. | 
					
						
							|  |  |  |     For example, there is no point in re-exporting `HttpModule` because it doesn't export anything. | 
					
						
							|  |  |  |     It's only purpose is to add http service providers to the application as a whole. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-for-root | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What is the _forRoot_ method? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The `forRoot` static method is a convention that makes it easy for developers to configure the module's provider(s). | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   The `RouterModule.forRoot` method is a good example.  | 
					
						
							|  |  |  |   Apps pass a `Routes` object to `RouterModule.forRoot` in order to configure the app-wide `Router` service with routes.  | 
					
						
							|  |  |  |   `RouterModule.forRoot` returns a [ModuleWithProviders](../api/core/index/ModuleWithProviders-interface.html).  | 
					
						
							|  |  |  |   We add that result to the `imports` list of the root `AppModule`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .alert.is-important | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Only call and import a `.forRoot` result in the root application module, `AppModule`. | 
					
						
							|  |  |  |     Importing it in any other module, particularly in a lazy loaded module, | 
					
						
							|  |  |  |     is contrary to the intent and is likely to produce a runtime error. | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   `RouterModule` also offers a `forChild` static method for configuring the routes of lazy loaded modules. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   **_forRoot_** and **_forChild_** are conventional names for methods that | 
					
						
							|  |  |  |   configure services in root and feature modules respectively. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Angular doesn't recognize these names but Angular developers do. | 
					
						
							|  |  |  |   Follow this convention when you write similar modules with configurable service providers. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-module-provider-visibility | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Why is a service provided in a feature module visible everywhere? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Providers listed in the `@NgModule.providers` of a bootstrapped module have **application scope**. | 
					
						
							|  |  |  |   Adding a service provider to `@NgModule.providers` effectively publishes the service to the entire application. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When we import a module, | 
					
						
							|  |  |  |   Angular adds the module's service providers (the contents of its `providers` list) | 
					
						
							|  |  |  |   to the application _root injector_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This makes the provider visible to every class in the application that knows the provider's lookup token. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This is by design.  | 
					
						
							|  |  |  |   Extensibility through module imports is a primary goal of the Angular module system. | 
					
						
							|  |  |  |   Merging module providers into the application injector | 
					
						
							|  |  |  |   makes it easy for a module library to enrich the entire application with new services. | 
					
						
							|  |  |  |   By adding the `HttpModule` once, every application component can make http requests.  | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   However, this can feel like an unwelcome surprise if you are expecting the module's services  | 
					
						
							|  |  |  |   to be visible only to the components declared by that feature module. | 
					
						
							|  |  |  |   If the `HeroModule` provides the `HeroService` and the root `AppModule` imports `HeroModule`,  | 
					
						
							|  |  |  |   any class that knows the `HeroService` _type_ can inject that service,  | 
					
						
							|  |  |  |   not just the classes declared in the `HeroModule`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-lazy-loaded-module-provider-visibility | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Why is a service provided in a lazy loaded module visible only to that module? | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Unlike providers of the modules loaded at launch,  | 
					
						
							|  |  |  |   providers of lazy loaded modules are *module-scoped*. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When the Angular router lazy-loads a module, it creates a new execution context. | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   That [context has its own injector](#q-why-child-injector "Why Angular creates a child injector") which is a direct child of the application injector. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   The router adds the lazy module's providers and the providers of its imported modules to this child injector. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   These providers are insulated from changes to application providers with the same lookup token. | 
					
						
							|  |  |  |   When the router creates a component within the lazy loaded context, | 
					
						
							|  |  |  |   Angular prefers service instances created from these providers to the service instances of the application root injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | a#q-module-provider-duplicates | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What if two modules provide the _same_ service? | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   When two imported modules, loaded at the same time, list a provider with the same token,  | 
					
						
							|  |  |  |   the second module's provider "wins". That's because both providers are added to the same injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When Angular looks to inject a service for that token,  | 
					
						
							|  |  |  |   it creates and delivers the instance created by the second provider. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   _Every_ class that injects this service gets the instance created by the second provider. | 
					
						
							|  |  |  |   Even classes declared within the first module get the instance created by the second provider. | 
					
						
							|  |  |  |   _This can be an unwelcome surprise_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   If Module A provides a service for token 'X' and imports a module B | 
					
						
							|  |  |  |   that also provides a service for token 'X', then Module A's service definition "wins". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The service provided by the root `AppModule` takes precedence over services provided by imported modules. | 
					
						
							|  |  |  |   The `AppModule` always wins. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-component-scoped-providers | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### How do I restrict service scope to a module? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When a module is loaded at application launch, | 
					
						
							|  |  |  |   its `@NgModule.providers` have ***application-wide scope***. | 
					
						
							|  |  |  |   They are visible throughout the application as discussed [above](#application-scoped-providers). | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Imported providers are easily replaced by providers from another imported module. | 
					
						
							|  |  |  |   Such replacement may be by design. It could be unintentional and have adverse consequences. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .alert.is-important | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     As a general rule, import modules with providers _exactly once_, preferably in the application's _root module_. | 
					
						
							|  |  |  |     That's also usually the best place to configure, wrap, and override them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Suppose a module requires a customized `HttpBackend` that adds a special header for all Http requests. | 
					
						
							|  |  |  |   If another module elsewhere in the application also customizes `HttpBackend` | 
					
						
							|  |  |  |   or merely imports the `HttpModule`, it could override this module's `HttpBackend` provider,  | 
					
						
							|  |  |  |   losing the special header. The server will reject http requests from this module. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .alert.is-important | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Avoid this problem by importing the `HttpModule` only in the `AppModule`, the application _root module_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   If you must guard against this kind of "provider corruption", *don't rely on a launch-time module's `providers`.* | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Load the module lazily if you can.  | 
					
						
							|  |  |  |   Angular gives a [lazy-loaded module](#q-lazy-loaded-module-provider-visibility) its own child injector. | 
					
						
							|  |  |  |   The module's providers are visible only within the component tree created with this injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   If you must load the module eagerly, when the application starts, | 
					
						
							|  |  |  |   ***provide the service in a component instead.*** | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Continuing with the same example, suppose the components of a module truly require a private, custom `HttpBackend`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Create a "top component" that acts as the root for all of the module's components.  | 
					
						
							|  |  |  |   Add the custom `HttpBackend` provider to the top component's `providers` list rather than the module's `providers`. | 
					
						
							|  |  |  |   Recall that Angular creates a child injector for each component instance and populates the injector | 
					
						
							|  |  |  |   with the component's own providers. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   When a child of this component _asks_ for the `HttpBackend` service, | 
					
						
							|  |  |  |   Angular provides the local `HttpBackend` service,  | 
					
						
							|  |  |  |   not the version provided in the application root injector. | 
					
						
							|  |  |  |   Child components will make proper http requests no matter what other modules do to `HttpBackend`. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Be sure to create module components as children of this module's top component. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   You can embed the child components in the top component's template. | 
					
						
							|  |  |  |   Alternatively, make the top component a routing host by giving it a `<router-outlet>`. | 
					
						
							|  |  |  |   Define child routes and let the router load module components into that outlet. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-root-component-or-module | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Should I add providers to the root _AppModule_ or the root _AppComponent_? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Most apps launch with an initial set of service providers.  | 
					
						
							| 
									
										
										
										
											2016-08-13 14:17:50 +08:00
										 |  |  |   Should we register those providers on the root `AppModule` (`@NgModule.providers`) or | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   the root `AppComponent` (`@Component.providers`)? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   **_List such providers in the root_ `AppModule` _unless you have a compelling reason to do otherwise_**. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Angular registers all startup module providers with the application root injector. | 
					
						
							|  |  |  |   The services created from root injector providers are available to the entire application.  | 
					
						
							|  |  |  |   They are _application-scoped_. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Certain services (e.g., the `Router`) only work when registered in the application root injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   By contrast, Angular registers `AppComponent` providers with the `AppComponent`'s own injector. | 
					
						
							|  |  |  |   `AppComponent`services are available to that component and its component tree.  | 
					
						
							|  |  |  |   They are _component-scoped_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The `AppComponent`'s injector is a _child_ of the root injector, one down in the injector hierarchy. | 
					
						
							|  |  |  |   That is _almost_ the entire application for apps that don't use the router. | 
					
						
							|  |  |  |   But "almost" isn't good enough for routed applications. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   `AppComponent` services don't exist at the root level where routing operates.  | 
					
						
							|  |  |  |   Lazy loaded modules can't reach them. | 
					
						
							|  |  |  |   In this sample applications, if we had registered `UserService` in the `AppComponent`,  | 
					
						
							|  |  |  |   the `HeroComponent` couldn't inject it. | 
					
						
							|  |  |  |   The application  would fail the moment a user navigated to "Heroes". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We _can_ register a service in `AppComponent` providers if the app doesn't use routing. | 
					
						
							|  |  |  |   We _should_ register a service in `AppComponent` providers if the service must be hidden | 
					
						
							|  |  |  |   from components outside the `AppComponent` tree.  | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   These are special cases. | 
					
						
							|  |  |  |   When in doubt, register with the `AppModule`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  | a#q-why-it-is-bad | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   ### Why is it bad if _SharedModule_ provides a service to a lazy loaded module? | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   This question arose earlier when we discussed the importance | 
					
						
							|  |  |  |   of keeping providers out of the [_SharedModule_](#no-shared-module-providers). | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Suppose we had listed the `UserService` in the module's `providers` (which we did not). | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   Suppose every module imports this `SharedModule` (which they all do). | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   When the app starts, Angular eagerly loads the `AppModule` and the `ContactModule`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Both instances of the imported `SharedModule` would provide the `UserService`.  | 
					
						
							|  |  |  |   Angular registers one of them in the root app injector (see [above](#q-reimport)). | 
					
						
							|  |  |  |   Then some component injects `UserService`, Angular finds it in the app root injector, | 
					
						
							|  |  |  |   and delivers the app-wide singleton `UserService`. No problem.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Now consider the `HeroModule` _which is lazy loaded!_ | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   When the router lazy loads the `HeroModule`, it creates a child injector and registers the `UserService` | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   provider with that child injector. The child injector is _not_ the root injector. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   When Angular creates a lazy `HeroComponent`, it must inject a `UserService`. | 
					
						
							|  |  |  |   This time it finds a `UserService` provider in the lazy module's _child injector_ | 
					
						
							|  |  |  |   and creates a _new_ instance of the `UserService`. | 
					
						
							|  |  |  |   This is an entirely different `UserService` instance | 
					
						
							|  |  |  |   than the app-wide singleton version that Angular injected in one of the eagerly loaded components. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   That's almost certainly a mistake. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Prove it for yourself. | 
					
						
							|  |  |  |     Run the <live-example>live example</live-example>. | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |     Modify the `SharedModule` so that it provides the `UserService` rather than the `CoreModule`. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |     Then toggle between the "Contact" and "Heroes" links a few times. | 
					
						
							|  |  |  |     The username goes bonkers as the Angular creates a new `UserService` instance each time. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | a#q-why-child-injector | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Why does lazy loading create a child injector? | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Angular adds `@NgModule.providers` to the application root injector ... unless the module is lazy loaded. | 
					
						
							|  |  |  |   Then it creates a _child injector_ and adds the module's providers to the child injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This means that a module behaves differently depending on whether it is loaded during application start | 
					
						
							|  |  |  |   or lazy loaded later. Neglecting that difference can lead to [adverse consequences](#q-why-it-is-bad). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Why doesn't Angular add lazy loaded providers to the app root injector as it does for eagerly loaded modules?  | 
					
						
							|  |  |  |   Why the inconsistency? | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   The answer is grounded in a fundamental characteristic of the Angular dependency injection system. | 
					
						
							|  |  |  |   An injector can add providers _until it is first used_.  | 
					
						
							|  |  |  |   Once an injector starts creating and delivering services, its provider list is frozen. No new providers allowed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When an applications starts, Angular first configures the root injector with the providers of all eagerly loaded modules | 
					
						
							|  |  |  |   _before_ creating its first component and injecting any of the provided services.  | 
					
						
							|  |  |  |   Once the application begins, the app root injector is closed to new providers. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Time passes. Application logic triggers lazy loading of a module. | 
					
						
							|  |  |  |   Angular must add the lazy loaded module's providers to an injector _somewhere_.  | 
					
						
							|  |  |  |   It can't added them to the app root injector because that injector is closed to new providers.  | 
					
						
							|  |  |  |   So Angular creates a new child injector for the lazy loaded module context. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-is-it-loaded | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### How can I tell if a module or service was previously loaded? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Some modules and its services should only be loaded once by the root `AppModule`. | 
					
						
							|  |  |  |   Importing the module a second time by lazy loading a module could [produce errant behavior](#q-why-it-is-bad)  | 
					
						
							|  |  |  |   that may be difficult to detect and diagnose. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We can guard against that danger by writing a constructor that attempts to inject the module or service | 
					
						
							|  |  |  |   from the root app injector. If the injection succeeds, the class has been loaded a second time. | 
					
						
							|  |  |  |   We can throw an error or take other remedial action. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Certain Angular modules (such as `BrowserModule`) implements such a guard  | 
					
						
							|  |  |  |   as does this sample's [_CoreModule_ constructor](#prevent-reimport). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | a#q-entry-component-defined | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What is an _entry component_? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Any component that Angular loads _imperatively_ by type is an _entry component_, | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   A component loaded _declaratively_ via its selector is _not_ an entry component. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Most application components are loaded declaratively.  | 
					
						
							|  |  |  |   Angular uses the component's selector to locate the element in the template.  | 
					
						
							|  |  |  |   It then creates the HTML representation of the component and inserts it into the DOM at the selected element. | 
					
						
							|  |  |  |   These are not entry components. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   A few components are only loaded dynamically and are _never_ referenced in a component template.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The bootstrapped root `AppComponent` is an _entry component_. | 
					
						
							|  |  |  |   True, its selector matches an element tag in `index.html`. | 
					
						
							|  |  |  |   But `index.html` is not a component template and the `AppComponent`  | 
					
						
							|  |  |  |   selector doesn't match an element in any component template. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Angular loads `AppComponent` dynamically either because we listed it _by type_ in `@NgModule.bootstrap`  | 
					
						
							|  |  |  |   or because we boostrapped it imperatively with the module's `ngDoBootstrap` method. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Components in route definitions are also _entry components_. | 
					
						
							|  |  |  |   A route definition refers to a component by its _type_.  | 
					
						
							|  |  |  |   The router ignores a routed component's selector (if it even has one) and  | 
					
						
							|  |  |  |   loads the component dynamically into a `RouterOutlet`.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The compiler can't discover these _entry components_ by looking for them in other component templates.  | 
					
						
							|  |  |  |   We must tell it about them ... by adding them to the `entryComponents` list. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Angular automatically adds two kinds of components to the module's `entryComponents`: | 
					
						
							| 
									
										
										
										
											2016-08-13 14:17:50 +08:00
										 |  |  |   1. the component in the `@NgModule.bootstrap` list | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   1. components referenced in router configuration | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We don't have to mention these components explicitly although it does not harm to do so. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-bootstrap_vs_entry_component | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What's the difference between a _bootstrap_ component and an _entry component_? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   A bootstrapped component _is_ an [entry component](#entry-component-defined). | 
					
						
							|  |  |  |   It's an entry component that Angular loads into the DOM during the bootstrap (application launch) process. | 
					
						
							| 
									
										
										
										
											2016-08-13 18:45:13 +08:00
										 |  |  |   Other entry components are loaded dynamically by other means such as with the router. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-13 18:50:37 +08:00
										 |  |  |   The `@NgModule.bootstrap` property tells the compiler _both_ that this is an entry component _and_ | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   that it should generate code to bootstrap the application with this component. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   There is no need to list a component in both the `bootstrap` and `entryComponent` lists  | 
					
						
							|  |  |  |   although it is harmless to do so. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-when-entry-components | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### When do I add components to _entryComponents_? | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2016-08-13 18:56:54 +08:00
										 |  |  |   Most application developers won't need to add components to the `entryComponents`. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |   Angular adds certain components to _entry components_ automatically. | 
					
						
							|  |  |  |   Components listed in `@NgModule.bootstrap` are added automatically. | 
					
						
							|  |  |  |   Components referenced in router configuration are added automatically. | 
					
						
							|  |  |  |   These two mechanisms account for almost all entry components. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   If your app happens to bootstrap or dynamically load a component _by type_ in some other manner,  | 
					
						
							|  |  |  |   you'll have to add it to `entryComponents` explicitly. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Although it's harmless to add components to this list, | 
					
						
							|  |  |  |   it's best to add only the components that are truly _entry components_. | 
					
						
							|  |  |  |   Don't include components that [are referenced](#q-template-reference)  | 
					
						
							|  |  |  |   in the templates of other components. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-why-entry-components | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Why does Angular need _entryComponents_? | 
					
						
							|  |  |  |   _Entry components_ are also declared. | 
					
						
							|  |  |  |   Why doesn't the Angular compiler generate code for every component in `@NgModule.declarations`? | 
					
						
							|  |  |  |   Then we wouldn't need entry components. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   The reason is _tree shaking_. For production apps we want to load the smallest, fastest code possible. | 
					
						
							|  |  |  |   The code should contain only the classes that we actually need. | 
					
						
							|  |  |  |   It should exclude a component that's never used, whether or not that component is declared. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   In fact, many libraries declare and export components we'll never use. | 
					
						
							|  |  |  |   The _tree shaker_ will drop these components from the final code package | 
					
						
							|  |  |  |   if we don't reference them.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   If the [Angular compiler](#angular-compilar) generated code for every declared component,  | 
					
						
							|  |  |  |   it would defeat the purpose of the tree shaker. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   Instead, the compiler adopts a recursive strategy that generates code only for the components we use. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   It starts with the entry components,  | 
					
						
							|  |  |  |   then it generates code for the declared components it [finds](#q-template-reference) in an entry component's template, | 
					
						
							|  |  |  |   then for the declared components it discovers in the templates of previously compiled components, | 
					
						
							|  |  |  |   and so on. At the end of the process, it has generated code for every  entry component | 
					
						
							|  |  |  |   and every component reachable from an entry component. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   If a component isn't an _entry component_ or wasn't found in a template,  | 
					
						
							|  |  |  |   the compiler omits it.  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | a#q-module-recommendations | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   #### What kinds of modules should I have and how should I use them? | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Every app is different and developers have varying levels of experience and comfort with the available choices. | 
					
						
							|  |  |  |   Some suggestions and guidelines appear to have wide appeal. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | .alert.is-important | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     The following is preliminary guidance based on early experience using Angular modules in a few applications. | 
					
						
							|  |  |  |     Read with appropriate caution and reflection. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   #### _SharedModule_ | 
					
						
							|  |  |  |   Create a `SharedModule` with the components, directives, and pipes that you use | 
					
						
							|  |  |  |   everywhere in your app. This module should consist entirely of `declarations` | 
					
						
							|  |  |  |   most of them exported.  | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   It may re-export other [widget modules](#widget-feature-module) such as `CommonModule`, | 
					
						
							|  |  |  |   `FormsModule` and modules with the UI controls that you use most widely. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   It should ***not*** have `providers` for reasons [explained earlier](#q-why-it-is-bad). | 
					
						
							|  |  |  |   Nor should any of its imported or re-exported modules have `providers`. | 
					
						
							|  |  |  |   Know what you're doing and why if you deviate from this guideline. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Import the `SharedModule` in your _feature_ modules,  | 
					
						
							|  |  |  |   both those loaded when the app starts and those you lazy load later. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   #### _CoreModule_ | 
					
						
							|  |  |  |   Create a `CoreModule` with `providers` for the singleton services you load when the application starts. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Import `CoreModule` in the root `AppModule` only. | 
					
						
							|  |  |  |   Never import `CoreModule` in any module other than the root `AppModule`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Consider making `CoreModule` a [pure services module](#service-feature-module) with no `declarations`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     This chapter sample departs from that advice by declaring and exporting two components that are | 
					
						
							|  |  |  |     only used within the root `AppComponent` declared by `AppModule`.  | 
					
						
							|  |  |  |     Someone following this guideline strictly would have declared these components in the `AppModule` instead. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   #### Feature Modules | 
					
						
							|  |  |  |   Create _Feature Modules_ around specific application business domains, user workflows, and utility collections. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |    | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Feature modules tend to fall into one of these four groups: | 
					
						
							|  |  |  |     * [Domain Feature Modules](#domain-feature-module) | 
					
						
							|  |  |  |     * [Routed Feature Modules](#routed-feature-module) | 
					
						
							|  |  |  |     * [Service Feature Modules](#service-feature-module) | 
					
						
							|  |  |  |     * [Widget Feature Modules](#widget-feature-module) | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Real world modules are often hybrids that knowingly deviate from the following guidelines. | 
					
						
							|  |  |  |     They are guidelines, not laws. | 
					
						
							|  |  |  |     Follow them until you have a good reason to do otherwise. | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | table | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     th(style="vertical-align: top") Feature Module | 
					
						
							|  |  |  |     th(style="vertical-align: top") Guidelines | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top")<a id="domain-feature-module"></a>Domain | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							|  |  |  |         Domain Feature Modules deliver a user experience **dedicated to a particular application domain** | 
					
						
							|  |  |  |         like editing a customer or placing an order. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         They typically have a top component that acts as the feature root. | 
					
						
							|  |  |  |         Private, supporting sub-components descend from it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Domain feature module consist mostly of _declarations_. | 
					
						
							|  |  |  |         Only the top component is exported. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Domain feature modules rarely have _providers_. | 
					
						
							|  |  |  |         When they do, the lifetime of the provided services | 
					
						
							|  |  |  |         should be the same as the lifetime of the module. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         Do not provide application-wide singleton services in a domain feature module. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Domain feature modules are typically imported _exactly once_ by a larger feature module. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         They might be imported by the root `AppModule` of a small application that lacks routing. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       .l-sub-section | 
					
						
							|  |  |  |         :marked | 
					
						
							|  |  |  |           For an example, see this chapter's first version of the [_ContactModule_](#contact-module-v1) | 
					
						
							|  |  |  |           before we introduced routing. | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top")<a id="routed-feature-module"></a>Routed | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							|  |  |  |         _Routed Feature Modules_ are _Domain Feature modules_  | 
					
						
							|  |  |  |         whose top components are the **targets of router navigation routes**. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         All lazy loaded modules are routed feature modules by nature. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This chapter's `ContactModule`, `HeroModule` and `CrisisModule` are routed feature modules. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Routed Feature Modules _should not export anything_.  | 
					
						
							|  |  |  |         They don't have to because none of their components ever appear in the template of an external component. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Routed Feature Modules are _never imported_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Routed Feature Modules rarely have _providers_ for reasons [explained earlier](#q-why-it-is-bad). | 
					
						
							|  |  |  |         When they do, the lifetime of the provided services | 
					
						
							|  |  |  |         should be the same as the lifetime of the module. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         Do not provide application-wide singleton services in a routed feature module | 
					
						
							|  |  |  |         or in a module that the routed module imports. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top")<a id="service-feature-module"></a>Service | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							|  |  |  |         _Service Modules_ **provide utility services** such as data access and messaging. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Ideally they consist entirely of _providers_ and have no _declarations_. | 
					
						
							|  |  |  |         The `CoreModule` and Angular's `HttpModule` are good examples. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Service Modules should _only_ be imported by the root `AppModule`. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         Do **not** import them in other feature modules. | 
					
						
							|  |  |  |         Know what you're doing and why if you deviate from this guideline. | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td(style="vertical-align: top")<a id="widget-feature-module"></a>Widget | 
					
						
							|  |  |  |     td | 
					
						
							|  |  |  |       :marked | 
					
						
							|  |  |  |         A _Widget Module_ makes **components, directives, and pipes** available to external modules. | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         `CommonModule` and `SharedModule` are widget modules. | 
					
						
							|  |  |  |         Many third party UI component libraries are widget modules. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         A Widget Module should consist entirely of _declarations_, most of them exported.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         A Widget Module should rarely have _providers_.  | 
					
						
							|  |  |  |         Know what you're doing and why if you deviate from this guideline. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Import Widget Modules in any module whose component templates need the widgets. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The following table summarizes the key characteristics of each _Feature Module_ group. | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Real world modules are often hybrids that knowingly deviate from these guidelines. | 
					
						
							|  |  |  | table | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     th Feature Module | 
					
						
							|  |  |  |     th Declarations  | 
					
						
							|  |  |  |     th Providers  | 
					
						
							|  |  |  |     th Exports | 
					
						
							|  |  |  |     th Imported By | 
					
						
							|  |  |  |     th Examples | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td Domain | 
					
						
							|  |  |  |     td Yes | 
					
						
							|  |  |  |     td Rare | 
					
						
							|  |  |  |     td Top Component | 
					
						
							|  |  |  |     td Feature, <code>AppModule</code> | 
					
						
							|  |  |  |     td <code>ContactModule</code> (before routing) | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td Routed | 
					
						
							|  |  |  |     td Yes | 
					
						
							|  |  |  |     td Rare | 
					
						
							|  |  |  |     td None | 
					
						
							|  |  |  |     td Nobody | 
					
						
							|  |  |  |     td <code>ContactModule</code>, <code>HeroModule</code>, <code>CrisisModule</code> | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td Service | 
					
						
							|  |  |  |     td No | 
					
						
							|  |  |  |     td Yes | 
					
						
							|  |  |  |     td No | 
					
						
							|  |  |  |     td <code>AppModule</code> | 
					
						
							|  |  |  |     td <code>HttpModule</code>, <code>CoreModule</code> | 
					
						
							|  |  |  |   tr | 
					
						
							|  |  |  |     td Widget | 
					
						
							|  |  |  |     td Yes | 
					
						
							|  |  |  |     td Rare | 
					
						
							|  |  |  |     td Yes | 
					
						
							|  |  |  |     td Feature | 
					
						
							|  |  |  |     td <code>CommonModule</code>, <code>SharedModule</code> | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-ng-vs-js-modules | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### What's the difference between Angular and JavaScript Modules? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Angular and JavaScript are two different yet complementary module systems. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   In modern JavaScript, [every file is a _module_](http://exploringjs.com/es6/ch_modules.html). | 
					
						
							|  |  |  |   Within each file we write an `export` statement to make parts of the module public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | code-example(format='.'). | 
					
						
							|  |  |  |   export class AppComponent { ... } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Then we `import` a part in another module: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | code-example(format='.'). | 
					
						
							|  |  |  |   import { AppComponent }  from './app.component'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   This kind of modularity is a feature of the _JavaScript language_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   An _Angular Module_ is a feature of _Angular_ itself. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   Angular's `NgModule` also has `imports` and `exports` and they serve a similar purpose.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We _import_ other Angular modules so we can use their exported classes in component templates. | 
					
						
							|  |  |  |   We _export_ this Angular module's classes so they can be imported and used by components of _other_ modules. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   The Angular module classes differ from JavaScript module class in three key respects: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   1. An Angular module bounds [_declarable classes_](#q-declarables) only.  | 
					
						
							|  |  |  |   Declarables are the only classes that matter to the [Angular compiler](#angular-compiler). | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   1. Instead of defining all member classes in one giant file (as in a JavaScript module), | 
					
						
							|  |  |  |      we list the module's classes in the `@NgModule.declarations` list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   1. An Angular module can only export the [_declarable classes_](#q-declarables)  | 
					
						
							|  |  |  |   it owns or imports from other modules. | 
					
						
							|  |  |  |   It doesn't declare or export any other kind of class. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The Angular Module is also special in another way. | 
					
						
							|  |  |  |   Unlike JavaScript modules, an Angular module can extend the _entire_ application with services | 
					
						
							|  |  |  |   by adding providers to the `@NgModule.providers` list. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .alert.is-important | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     The provided services do not belong to the module nor are they scoped to the declared classes. | 
					
						
							|  |  |  |     They are available _everywhere_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  |   Here's an _Angular Module_ class with imports, exports, and declarations. | 
					
						
							|  |  |  | +makeExample('ngmodule/ts/app/contact/contact.module.2.ts', 'class')(format=".") | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Of course we use _JavaScript_ modules to write _Angular_ modules as seen in the complete `contact.module.ts` file: | 
					
						
							|  |  |  | +makeExample('ngmodule/ts/app/contact/contact.module.2.ts', '', 'app/contact/contact.module.ts')(format=".") | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-template-reference | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | h4. | 
					
						
							|  |  |  |   How does Angular find components, directives, and pipes in a template?<br>What is a <i><b>template reference</b></i>? | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The [Angular compiler](#q-angular-compiler) looks inside component templates  | 
					
						
							|  |  |  |   for other components, directives, and pipes. When it finds one, that's a "template reference". | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The Angular compiler finds a component or directive in a template when it can match the **selector** of that  | 
					
						
							|  |  |  |   component or directive to some HTML in that template.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The compiler finds a pipe if the pipe's **name** appears within the pipe syntax of the template HTML. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Angular only matches selectors and pipe names for classes that are declared by this module | 
					
						
							|  |  |  |   or exported by a module that this module imports. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-hr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | a#q-angular-compiler   | 
					
						
							|  |  |  | .l-main-section | 
					
						
							| 
									
										
										
										
											2016-07-12 18:14:13 -07:00
										 |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-08-23 00:17:18 -07:00
										 |  |  |   ### What is the Angular Compiler? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The _Angular Compiler_ converts the application code we write into highly performant JavaScript code. | 
					
						
							|  |  |  |   The `@NgModule` metadata play an important role in guiding the compilation process. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The code we write is not immediately executable. | 
					
						
							|  |  |  |   Consider **components**. | 
					
						
							|  |  |  |   Components have templates that contain custom elements, attribute directives, Angular binding declarations,  | 
					
						
							|  |  |  |   and some peculiar syntax that clearly isn't native HTML. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   The _Angular Compiler_ reads the template markup,  | 
					
						
							|  |  |  |   combines it with the corresponding component class code, and emits _component factories_. | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   A component factory creates a pure, 100% JavaScript representation | 
					
						
							|  |  |  |   of the component that incorporates everything described in its `@Component` metadata:  | 
					
						
							|  |  |  |   the HTML, the binding instructions, the attached styles ... everything. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Because **directives** and **pipes** appear in component templates,  | 
					
						
							|  |  |  |   the _Angular Compiler_ incorporates them into compiled component code too. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   `@NgModule` metadata tells the _Angular Compiler_ what components to compile for this module and  | 
					
						
							|  |  |  |   how to link this module with other modules. |