diff --git a/.circleci/config.yml b/.circleci/config.yml index bc61db14ba..02acd29517 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -7,7 +7,7 @@ jobs: build: docker: # specify the version you desire here - - image: circleci/node:boron + - image: circleci/node:carbon # Specify service dependencies here if necessary # CircleCI maintains a library of pre-built images diff --git a/aio-ja/content/guide/ajs-quick-reference.md b/aio-ja/content/guide/ajs-quick-reference.md index f6eaaca4fc..2a345c9b1e 100644 --- a/aio-ja/content/guide/ajs-quick-reference.md +++ b/aio-ja/content/guide/ajs-quick-reference.md @@ -212,8 +212,6 @@ The following are some of the key AngularJS built-in directives and their equiva To launch the app in code, explicitly bootstrap the application's root module (`AppModule`) in `main.ts` and the application's root component (`AppComponent`) in `app.module.ts`. - - For more information see the [Setup](guide/setup) page. @@ -1254,13 +1252,12 @@ also encapsulate a style sheet within a specific component. - ### Link tag - - + ### Styles configuration + - In Angular, you can continue to use the link tag to define the styles for your application in the `index.html` file. - But now you can also encapsulate styles for your components. + With the Angular CLI, you can configure your global styles in the `.angular-cli.json` file. + You can rename the extension to `.scss` to use sass. ### StyleUrls In Angular, you can use the `styles` or `styleUrls` property of the `@Component` metadata to define diff --git a/aio-ja/content/guide/aot-compiler.md b/aio-ja/content/guide/aot-compiler.md index 9c32535893..2f126c0ad1 100644 --- a/aio-ja/content/guide/aot-compiler.md +++ b/aio-ja/content/guide/aot-compiler.md @@ -2,7 +2,7 @@ The Angular Ahead-of-Time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase _before_ the browser downloads and runs that code. -This guide explains how to to build with the AOT compiler and how to write Angular metadata that AOT can compile. +This guide explains how to build with the AOT compiler and how to write Angular metadata that AOT can compile.
@@ -127,7 +127,7 @@ You can think of `.metadata.json` as a diagram of the overall structure of a dec
-Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/tsc-wrapped/src/schema.ts) +Angular's [schema.ts](https://github.com/angular/angular/blob/master/packages/compiler-cli/src/metadata/schema.ts) describes the JSON format as a collection of TypeScript interfaces.
@@ -409,7 +409,7 @@ function; it can only contain a single `return` statement. The Angular [`RouterModule`](api/router/RouterModule) exports two macro static methods, `forRoot` and `forChild`, to help declare root and child routes. Review the [source code](https://github.com/angular/angular/blob/master/packages/router/src/router_module.ts#L139 "RouterModule.forRoot source code") -for these methods to see how macros can simplify configuration of complex Angular modules. +for these methods to see how macros can simplify configuration of complex [NgModules](guide/ngmodule). ### Metadata rewriting diff --git a/aio-ja/content/guide/attribute-directives.md b/aio-ja/content/guide/attribute-directives.md index 9c0daebdc6..05d07bf400 100644 --- a/aio-ja/content/guide/attribute-directives.md +++ b/aio-ja/content/guide/attribute-directives.md @@ -33,7 +33,7 @@ An attribute directive minimally requires building a controller class annotated the attribute. The controller class implements the desired directive behavior. -This page demonstrates building a simple _myHighlight_ attribute +This page demonstrates building a simple _appHighlight_ attribute directive to set an element's background color when the user hovers over that element. You can apply it like this: @@ -43,106 +43,84 @@ when the user hovers over that element. You can apply it like this: ### Write the directive code -Follow the [setup](guide/setup) instructions for creating a new local project -named attribute-directives. +Create the directive class file in a terminal window with this CLI command. -Create the following source file in the indicated folder: + +ng generate directive highlight + - +The CLI creates `src/app/highlight.directive.ts`, a corresponding test file (`.../spec.ts`, and _declares_ the directive class in the root `AppModule`. + +
+ +_Directives_ must be declared in [Angular Modules](guide/ngmodule) in the same manner as _components_. + +
+ +The generated `src/app/highlight.directive.ts` is as follows: -The `import` statement specifies symbols from the Angular `core`: + -1. `Directive` provides the functionality of the `@Directive` decorator. -1. `ElementRef` [injects](guide/dependency-injection) into the directive's constructor -so the code can access the DOM element. -1. `Input` allows data to flow from the binding expression into the directive. +The imported `Directive` symbol provides the Angular the `@Directive` decorator. -Next, the `@Directive` decorator function contains the directive metadata in a configuration object -as an argument. +The `@Directive` decorator's lone configuration property specifies the directive's +[CSS attribute selector](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors), `[appHighlight]`. -`@Directive` requires a CSS selector to identify -the HTML in the template that is associated with the directive. -The [CSS selector for an attribute](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) -is the attribute name in square brackets. -Here, the directive's selector is `[myHighlight]`. -Angular locates all elements in the template that have an attribute named `myHighlight`. +It's the brackets (`[]`) that make it an attribute selector. +Angular locates each element in the template that has an attribute named `appHighlight` and applies the logic of this directive to that element. + +The _attribute selector_ pattern explains the name of this kind of directive.
-### Why not call it "highlight"? +#### Why not "highlight"? -Though *highlight* is a more concise name than *myHighlight* and would work, -a best practice is to prefix selector names to ensure +Though *highlight* would be a more concise selector than *appHighlight* and it would work, +the best practice is to prefix selector names to ensure they don't conflict with standard HTML attributes. This also reduces the risk of colliding with third-party directive names. +The CLI added the `app` prefix for you. Make sure you do **not** prefix the `highlight` directive name with **`ng`** because that prefix is reserved for Angular and using it could cause bugs that are difficult to diagnose. -For a simple demo, the short prefix, `my`, helps distinguish your custom directive.
- After the `@Directive` metadata comes the directive's controller class, -called `HighlightDirective`, which contains the logic for the directive. -Exporting `HighlightDirective` makes it accessible to other components. - -Angular creates a new instance of the directive's controller class for -each matching element, injecting an Angular `ElementRef` -into the constructor. -`ElementRef` is a service that grants direct access to the DOM element -through its `nativeElement` property. +called `HighlightDirective`, which contains the (currently empty) logic for the directive. +Exporting `HighlightDirective` makes the directive accessible. -{@a apply-directive} - -## Apply the attribute directive +Now edit the generated `src/app/highlight.directive.ts` to look as follows: -To use the new `HighlightDirective`, create a template that -applies the directive as an attribute to a paragraph (`

`) element. -In Angular terms, the `

` element is the attribute **host**. + -Put the template in its own app.component.html -file that looks like this: +The `import` statement specifies an additional `ElementRef` symbol from the Angular `core` library: - +You use the `ElementRef`in the directive's constructor +to [inject](guide/dependency-injection) a reference to the host DOM element, +the element to which you applied `appHighlight`. -Now reference this template in the `AppComponent`: +`ElementRef` grants direct access to the host DOM element +through its `nativeElement` property. - +This first implementation sets the background color of the host element to yellow. -Next, add an `import` statement to fetch the `Highlight` directive and -add that class to the `declarations` NgModule metadata. This way Angular -recognizes the directive when it encounters `myHighlight` in the template. +{@a apply-directive} - +## Apply the attribute directive -Now when the app runs, the `myHighlight` directive highlights the paragraph text. +To use the new `HighlightDirective`, add a paragraph (`

`) element to the template of the root `AppComponent` and apply the directive as an attribute. -

- First Highlight -
+ -
+Now run the application to see the `HighlightDirective` in action. -

Your directive isn't working?

-Did you remember to add the directive to the `declarations` attribute of `@NgModule`? -It is easy to forget! -Open the console in the browser tools and look for an error like this: - - - EXCEPTION: Template parse errors: - Can't bind to 'myHighlight' since it isn't a known property of 'p'. + +ng serve -Angular detects that you're trying to bind to *something* but it can't find this directive -in the module's `declarations` array. -After specifying `HighlightDirective` in the `declarations` array, -Angular knows it can apply the directive to components declared in this module. - -
- -To summarize, Angular found the `myHighlight` attribute on the `

` element. +To summarize, Angular found the `appHighlight` attribute on the **host** `

` element. It created an instance of the `HighlightDirective` class and injected a reference to the `

` element into the directive's constructor which sets the `

` element's background style to yellow. @@ -151,15 +129,14 @@ which sets the `

` element's background style to yellow. ## Respond to user-initiated events -Currently, `myHighlight` simply sets an element color. +Currently, `appHighlight` simply sets an element color. The directive could be more dynamic. It could detect when the user mouses into or out of the element and respond by setting or clearing the highlight color. -Begin by adding `HostListener` to the list of imported symbols; -add the `Input` symbol as well because you'll need it soon. +Begin by adding `HostListener` to the list of imported symbols. - + Then add two eventhandlers that respond when the mouse enters or leaves, each adorned by the `HostListener` decorator. @@ -180,8 +157,10 @@ There are at least three problems with _that_ approach:

-The handlers delegate to a helper method that sets the color on the DOM element, `el`, -which you declare and initialize in the constructor. +The handlers delegate to a helper method that sets the color on the host DOM element, `el`. + +The helper method, `highlight`, was extracted from the constructor. +The revised constructor simply declares the injected `el: ElementRef`. @@ -203,7 +182,10 @@ the mouse hovers over the `p` and disappears as it moves out. Currently the highlight color is hard-coded _within_ the directive. That's inflexible. In this section, you give the developer the power to set the highlight color while applying the directive. -Start by adding a `highlightColor` property to the directive class like this: +Begin by adding `Input` to the list of symbols imported from `@angular/core`. + + +Add a `highlightColor` property to the directive class like this: @@ -232,16 +214,16 @@ That's good, but it would be nice to _simultaneously_ apply the directive and se -The `[myHighlight]` attribute binding both applies the highlighting directive to the `

` element +The `[appHighlight]` attribute binding both applies the highlighting directive to the `

` element and sets the directive's highlight color with a property binding. -You're re-using the directive's attribute selector (`[myHighlight]`) to do both jobs. +You're re-using the directive's attribute selector (`[appHighlight]`) to do both jobs. That's a crisp, compact syntax. -You'll have to rename the directive's `highlightColor` property to `myHighlight` because that's now the color property binding name. +You'll have to rename the directive's `highlightColor` property to `appHighlight` because that's now the color property binding name. -This is disagreeable. The word, `myHighlight`, is a terrible property name and it doesn't convey the property's intent. +This is disagreeable. The word, `appHighlight`, is a terrible property name and it doesn't convey the property's intent. {@a input-alias} @@ -254,14 +236,14 @@ Restore the original property name and specify the selector as the alias in the _Inside_ the directive the property is known as `highlightColor`. -_Outside_ the directive, where you bind to it, it's known as `myHighlight`. +_Outside_ the directive, where you bind to it, it's known as `appHighlight`. You get the best of both worlds: the property name you want and the binding syntax you want: -Now that you're binding to `highlightColor`, modify the `onMouseEnter()` method to use it. -If someone neglects to bind to `highlightColor`, highlight in red: +Now that you're binding via the alias to the `highlightColor`, modify the `onMouseEnter()` method to use that property. +If someone neglects to bind to `appHighlightColor`, highlight the host element in red: @@ -308,7 +290,7 @@ then with the `defaultColor`, and falls back to "red" if both properties are und -How do you bind to a second property when you're already binding to the `myHighlight` attribute name? +How do you bind to a second property when you're already binding to the `appHighlight` attribute name? As with components, you can add as many directive property bindings as you need by stringing them along in the template. The developer should be able to write the following template HTML to both bind to the `AppComponent.color` @@ -398,6 +380,6 @@ Now apply that reasoning to the following example: The template and its component trust each other. The `color` property doesn't require the `@Input` decorator. -* The `myHighlight` property on the left refers to an _aliased_ property of the `HighlightDirective`, +* The `appHighlight` property on the left refers to an _aliased_ property of the `HighlightDirective`, not a property of the template's component. There are trust issues. Therefore, the directive property must carry the `@Input` decorator. diff --git a/aio-ja/content/guide/component-interaction.md b/aio-ja/content/guide/component-interaction.md index 69d07c8c55..3a07f918a9 100644 --- a/aio-ja/content/guide/component-interaction.md +++ b/aio-ja/content/guide/component-interaction.md @@ -356,6 +356,7 @@ Use `setTimeout()` to wait one tick and then revise the `seconds()` method so that it takes future values from the timer component.

Test it

+ Use [the same countdown timer tests](guide/component-interaction#countdown-tests) as before. [Back to top](guide/component-interaction#top) diff --git a/aio-ja/content/guide/component-styles.md b/aio-ja/content/guide/component-styles.md index 9b383b776c..9fd7d293fb 100644 --- a/aio-ja/content/guide/component-styles.md +++ b/aio-ja/content/guide/component-styles.md @@ -179,7 +179,7 @@ to a component's `@Component` decorator: - +
@@ -245,7 +245,8 @@ See the [CLI documentation](https://github.com/angular/angular-cli/wiki/stories- ### Non-CSS style files -You can write style files in [sass](http://sass-lang.com/), [less](http://lesscss.org/), or [stylus](http://stylus-lang.com/) and specify those files in the `styleUrls` metadata, e.g., +If you're building with the CLI, +you can write style files in [sass](http://sass-lang.com/), [less](http://lesscss.org/), or [stylus](http://stylus-lang.com/) and specify those files in the `@Component.styleUrls` metadata with the appropriate extensions (`.scss`, `.less`, `.styl`) as in the following example: @Component({ @@ -256,10 +257,18 @@ You can write style files in [sass](http://sass-lang.com/), [less](http://lesscs ... -The CLI build process runs the corresponding CSS pre-processors. +The CLI build process runs the pertinent CSS preprocessor. -You can also configure the CLI to default to your preferred CSS pre-processer -as explained in the [CLI documentation](https://github.com/angular/angular-cli/wiki/stories-css-preprocessors). +When generating a component file with `ng generate component`, the CLI emits an empty CSS styles file (`.css`) by default. +You can configure the CLI to default to your preferred CSS preprocessor +as explained in the [CLI documentation](https://github.com/angular/angular-cli/wiki/stories-css-preprocessors +"CSS Preprocessor integration"). + +
+ +Style strings added to the `@Component.styles` array _must be written in CSS_ because the CLI cannot apply a preprocessor to inline styles. + +
{@a view-encapsulation} diff --git a/aio-ja/content/guide/dependency-injection-in-action.md b/aio-ja/content/guide/dependency-injection-in-action.md index e974c3e643..46a6cd11d5 100644 --- a/aio-ja/content/guide/dependency-injection-in-action.md +++ b/aio-ja/content/guide/dependency-injection-in-action.md @@ -5,51 +5,6 @@ Dependency Injection is a powerful pattern for managing code dependencies. This cookbook explores many of the features of Dependency Injection (DI) in Angular. {@a toc} - - See the of the code in this cookbook. @@ -79,7 +34,7 @@ is all the registration you need. A *provider* is something that can create or deliver a service. Angular creates a service instance from a class provider by using `new`. -Read more about providers in the [Dependency Injection](guide/dependency-injection#injector-providers) +Read more about providers in the [Dependency Injection](guide/dependency-injection#register-providers-ngmodule) guide.
diff --git a/aio-ja/content/guide/dependency-injection-pattern.md b/aio-ja/content/guide/dependency-injection-pattern.md new file mode 100644 index 0000000000..d13f2baa3a --- /dev/null +++ b/aio-ja/content/guide/dependency-injection-pattern.md @@ -0,0 +1,167 @@ +# The Dependency Injection pattern + +**Dependency injection** is an important application design pattern. +It's used so widely that almost everyone just calls it _DI_. + +Angular has its own dependency injection framework, and +you really can't build an Angular application without it. + +This page covers what DI is and why it's useful. + +When you've learned the general pattern, you're ready to turn to +the [Angular Dependency Injection](guide/dependency-injection) guide to see how it works in an Angular app. + +{@a why-di } + +## Why dependency injection? + +To understand why dependency injection is so important, consider an example without it. +Imagine writing the following code: + + + + +The `Car` class creates everything it needs inside its constructor. +What's the problem? +The problem is that the `Car` class is brittle, inflexible, and hard to test. + +This `Car` needs an engine and tires. Instead of asking for them, +the `Car` constructor instantiates its own copies from +the very specific classes `Engine` and `Tires`. + +What if the `Engine` class evolves and its constructor requires a parameter? +That would break the `Car` class and it would stay broken until you rewrote it along the lines of +`this.engine = new Engine(theNewParameter)`. +The `Engine` constructor parameters weren't even a consideration when you first wrote `Car`. +You may not anticipate them even now. +But you'll *have* to start caring because +when the definition of `Engine` changes, the `Car` class must change. +That makes `Car` brittle. + +What if you want to put a different brand of tires on your `Car`? Too bad. +You're locked into whatever brand the `Tires` class creates. That makes the +`Car` class inflexible. + +Right now each new car gets its own `engine`. It can't share an `engine` with other cars. +While that makes sense for an automobile engine, +surely you can think of other dependencies that should be shared, such as the onboard +wireless connection to the manufacturer's service center. This `Car` lacks the flexibility +to share services that have been created previously for other consumers. + +When you write tests for `Car` you're at the mercy of its hidden dependencies. +Is it even possible to create a new `Engine` in a test environment? +What does `Engine` depend upon? What does that dependency depend on? +Will a new instance of `Engine` make an asynchronous call to the server? +You certainly don't want that going on during tests. + +What if the `Car` should flash a warning signal when tire pressure is low? +How do you confirm that it actually does flash a warning +if you can't swap in low-pressure tires during the test? + +You have no control over the car's hidden dependencies. +When you can't control the dependencies, a class becomes difficult to test. + +How can you make `Car` more robust, flexible, and testable? + +{@a ctor-injection} +That's super easy. Change the `Car` constructor to a version with DI: + + + + + + + + + + + +See what happened? The definition of the dependencies are +now in the constructor. +The `Car` class no longer creates an `engine` or `tires`. +It just consumes them. + +
+ +This example leverages TypeScript's constructor syntax for declaring +parameters and properties simultaneously. + +
+ +Now you can create a car by passing the engine and tires to the constructor. + + + + +How cool is that? +The definition of the `engine` and `tire` dependencies are +decoupled from the `Car` class. +You can pass in any kind of `engine` or `tires` you like, as long as they +conform to the general API requirements of an `engine` or `tires`. + +Now, if someone extends the `Engine` class, that is not `Car`'s problem. + +
+ +The _consumer_ of `Car` has the problem. The consumer must update the car creation code to +something like this: + + + + + +The critical point is this: the `Car` class did not have to change. +You'll take care of the consumer's problem shortly. + +
+ +The `Car` class is much easier to test now because you are in complete control +of its dependencies. +You can pass mocks to the constructor that do exactly what you want them to do +during each test: + + + + +**You just learned what dependency injection is**. + +It's a coding pattern in which a class receives its dependencies from external +sources rather than creating them itself. + +Cool! But what about that poor consumer? +Anyone who wants a `Car` must now +create all three parts: the `Car`, `Engine`, and `Tires`. +The `Car` class shed its problems at the consumer's expense. +You need something that takes care of assembling these parts. + +You _could_ write a giant class to do that: + + + + +It's not so bad now with only three creation methods. +But maintaining it will be hairy as the application grows. +This factory is going to become a huge spiderweb of +interdependent factory methods! + +Wouldn't it be nice if you could simply list the things you want to build without +having to define which dependency gets injected into what? + +This is where the dependency injection framework comes into play. +Imagine the framework had something called an _injector_. +You register some classes with this injector, and it figures out how to create them. + +When you need a `Car`, you simply ask the injector to get it for you and you're good to go. + + + + +Everyone wins. The `Car` knows nothing about creating an `Engine` or `Tires`. +The consumer knows nothing about creating a `Car`. +You don't have a gigantic factory class to maintain. +Both `Car` and consumer simply ask for what they need and the injector delivers. + +This is what a **dependency injection framework** is all about. + +Now that you know what dependency injection is and appreciate its benefits, +turn to the [Angular Dependency Injection](guide/dependency-injection) guide to see how it is implemented in Angular. diff --git a/aio-ja/content/guide/dependency-injection.md b/aio-ja/content/guide/dependency-injection.md index 900f923a47..61c351cf8d 100644 --- a/aio-ja/content/guide/dependency-injection.md +++ b/aio-ja/content/guide/dependency-injection.md @@ -1,510 +1,266 @@ -# Dependency Injection +# Angular Dependency Injection -**Dependency injection** is an important application design pattern. -Angular has its own dependency injection framework, and -you really can't build an Angular application without it. -It's used so widely that almost everyone just calls it _DI_. +**Dependency Injection (DI)** is a way to create objects that depend upon other objects. +A Dependency Injection system supplies the dependent objects (called the _dependencies_) +when it creates an instance of an object. -This page covers what DI is, why it's so useful, -and [how to use it](guide/dependency-injection#angular-di) in an Angular app. +The [Dependency Injection pattern](guide/dependency-injection-pattern) page describes this general approach. +_The guide you're reading now_ explains how Angular's own Dependency Injection system works. -Run the . +## DI by example -{@a why-di } - -## Why dependency injection? - -To understand why dependency injection is so important, consider an example without it. -Imagine writing the following code: - - - - - - - - -The `Car` class creates everything it needs inside its constructor. -What's the problem? -The problem is that the `Car` class is brittle, inflexible, and hard to test. - -This `Car` needs an engine and tires. Instead of asking for them, -the `Car` constructor instantiates its own copies from -the very specific classes `Engine` and `Tires`. - -What if the `Engine` class evolves and its constructor requires a parameter? -That would break the `Car` class and it would stay broken until you rewrote it along the lines of -`this.engine = new Engine(theNewParameter)`. -The `Engine` constructor parameters weren't even a consideration when you first wrote `Car`. -You may not anticipate them even now. -But you'll *have* to start caring because -when the definition of `Engine` changes, the `Car` class must change. -That makes `Car` brittle. - -What if you want to put a different brand of tires on your `Car`? Too bad. -You're locked into whatever brand the `Tires` class creates. That makes the -`Car` class inflexible. - -Right now each new car gets its own `engine`. It can't share an `engine` with other cars. -While that makes sense for an automobile engine, -surely you can think of other dependencies that should be shared, such as the onboard -wireless connection to the manufacturer's service center. This `Car` lacks the flexibility -to share services that have been created previously for other consumers. - -When you write tests for `Car` you're at the mercy of its hidden dependencies. -Is it even possible to create a new `Engine` in a test environment? -What does `Engine` depend upon? What does that dependency depend on? -Will a new instance of `Engine` make an asynchronous call to the server? -You certainly don't want that going on during tests. - -What if the `Car` should flash a warning signal when tire pressure is low? -How do you confirm that it actually does flash a warning -if you can't swap in low-pressure tires during the test? - -You have no control over the car's hidden dependencies. -When you can't control the dependencies, a class becomes difficult to test. - -How can you make `Car` more robust, flexible, and testable? - -{@a ctor-injection} -That's super easy. Change the `Car` constructor to a version with DI: - - - - - - - - - - - - - - - - -See what happened? The definition of the dependencies are -now in the constructor. -The `Car` class no longer creates an `engine` or `tires`. -It just consumes them. - - -
- - - -This example leverages TypeScript's constructor syntax for declaring -parameters and properties simultaneously. - - -
- - - -Now you can create a car by passing the engine and tires to the constructor. - - - - - - - - -How cool is that? -The definition of the `engine` and `tire` dependencies are -decoupled from the `Car` class. -You can pass in any kind of `engine` or `tires` you like, as long as they -conform to the general API requirements of an `engine` or `tires`. - -Now, if someone extends the `Engine` class, that is not `Car`'s problem. - - -
- - - -The _consumer_ of `Car` has the problem. The consumer must update the car creation code to -something like this: - - - - - - - - -The critical point is this: the `Car` class did not have to change. -You'll take care of the consumer's problem shortly. - - -
- - - -The `Car` class is much easier to test now because you are in complete control -of its dependencies. -You can pass mocks to the constructor that do exactly what you want them to do -during each test: - - - - - - - - -**You just learned what dependency injection is**. - -It's a coding pattern in which a class receives its dependencies from external -sources rather than creating them itself. - -Cool! But what about that poor consumer? -Anyone who wants a `Car` must now -create all three parts: the `Car`, `Engine`, and `Tires`. -The `Car` class shed its problems at the consumer's expense. -You need something that takes care of assembling these parts. - -You _could_ write a giant class to do that: - - - - - - - - -It's not so bad now with only three creation methods. -But maintaining it will be hairy as the application grows. -This factory is going to become a huge spiderweb of -interdependent factory methods! - -Wouldn't it be nice if you could simply list the things you want to build without -having to define which dependency gets injected into what? - -This is where the dependency injection framework comes into play. -Imagine the framework had something called an _injector_. -You register some classes with this injector, and it figures out how to create them. - -When you need a `Car`, you simply ask the injector to get it for you and you're good to go. - - - - - - - - -Everyone wins. The `Car` knows nothing about creating an `Engine` or `Tires`. -The consumer knows nothing about creating a `Car`. -You don't have a gigantic factory class to maintain. -Both `Car` and consumer simply ask for what they need and the injector delivers. - -This is what a **dependency injection framework** is all about. - -Now that you know what dependency injection is and appreciate its benefits, -read on to see how it is implemented in Angular. - -{@a angular-di} - -## Angular dependency injection - -Angular ships with its own dependency injection framework. This framework can also be used -as a standalone module by other applications and frameworks. - -To see what it can do when building components in Angular, -start with a simplified version of the `HeroesComponent` -that from the [The Tour of Heroes](tutorial/). +You'll learn Angular Dependency Injection through a discussion of the sample app that accompanies this guide. +Run the anytime. +Start by reviewing this simplified version of the _heroes_ feature +from the [The Tour of Heroes](tutorial/). - - - + - - - +The `HeroesComponent` is the top-level heroes component. +It's only purpose is to display the `HeroListComponent` +which displays a list of hero names. +This version of the `HeroListComponent` gets its `heroes` from the `HEROES` array, an in-memory collection +defined in a separate `mock-heroes` file. -The `HeroesComponent` is the root component of the *Heroes* feature area. -It governs all the child components of this area. -This stripped down version has only one child, `HeroListComponent`, -which displays a list of heroes. - + + -Right now `HeroListComponent` gets heroes from `HEROES`, an in-memory collection -defined in another file. That may suffice in the early stages of development, but it's far from ideal. -As soon as you try to test this component or want to get your heroes data from a remote server, -you'll have to change the implementation of `heroes` and -fix every other use of the `HEROES` mock data. - -It's better to make a service that hides how the app gets hero data. - - -
+As soon as you try to test this component or get heroes from a remote server, +you'll have to change the implementation of `HerosListComponent` and +replace every other use of the `HEROES` mock data. +It's better to hide these details inside a _service_ class, +[defined in its own file](#one-class-per-file). +## Create an injectable _HeroService_ -Given that the service is a -[separate concern](https://en.wikipedia.org/wiki/Separation_of_concerns), -consider writing the service code in its own file. - -See [this note](guide/dependency-injection#one-class-per-file) for details. - -
+The [**Angular CLI**](https://cli.angular.io/) can generate a new `HeroService` class in the `src/app/heroes` folder with this command. + +ng generate service heroes/hero + +That command creates the following `HeroService` skeleton. -The following `HeroService` exposes a `getHeroes` method that returns -the same mock data as before, but none of its consumers need to know that. + + +Assume for now that the [`@Injectable` decorator](#injectable) is an essential ingredient in every Angular service definition. +The rest of the class has been rewritten to expose a `getHeroes` method +that returns the same mock data as before. - +Of course, this isn't a real data service. +If the app were actually getting data from a remote server, +the `getHeroes` method signature would have to be asynchronous. +That's a defect we can safely ignore in this guide where our focus is on +_injecting the service_ into the `HeroList` component. +{@a injector-config} +{@a bootstrap} -
- - +## Register a service provider -The `@Injectable()` decorator above the service class is -covered [shortly](guide/dependency-injection#injectable). +A _service_ is just a class in Angular until you register it with an Angular dependency injector. +An Angular injector is responsible for creating service instances and injecting them into classes like the `HeroListComponent`. -
+You rarely create an Angular injector yourself. +Angular creates injectors for you as it executes the app, +starting with the _root injector_ that it creates during the [bootstrap process](guide/bootstrapping). +You do have to register _providers_ with an injector +before the injector can create that service. +**Providers** tell the injector _how to create the service_. +Without a provider, the injector would not know +that it is responsible for injecting the service +nor be able to create the service.
- - -Of course, this isn't a real service. -If the app were actually getting data from a remote server, the API would have to be -asynchronous, perhaps returning a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). -You'd also have to rewrite the way components consume the service. -This is important in general, but not in this example. - - -
- - - -A service is nothing more than a class in Angular. -It remains nothing more than a class until you register it with an Angular injector. - - -
+You'll learn much more about _providers_ [below](#providers). +For now it is sufficient to know that they create services +and must be registered with an injector.
+You can register a provider with any Angular decorator that supports the **`providers` array property**. +Many Angular decorators accept metadata with a `providers` property. +The two most important examples are `@Component` and `@NgModule`. -{@a injector-config} - - -### Configuring the injector - -You don't have to create an Angular injector. -Angular creates an application-wide injector for you during the bootstrap process. +{@a register-providers-component} +### _@Component_ providers - +Here's a revised `HeroesComponent` that registers the `HeroService` in its `providers` array. + - - -You do have to configure the injector by registering the **providers** -that create the services the application requires. -This guide explains what [providers](guide/dependency-injection#providers) are later. - - -You can either register a provider within an [NgModule](guide/ngmodule) or in application components. - - {@a register-providers-ngmodule} +### _@NgModule_ providers -### Registering providers in an _NgModule_ -Here's the `AppModule` that registers two providers, `UserService` and an `APP_CONFIG` provider, -in its `providers` array. - - - +In the following excerpt, the root `AppModule` registers two providers in its `providers` array. + +The first entry registers the `UserService` class (_not shown_) under the `UserService` _injection token_. +The second registers a value (`HERO_DI_CONFIG`) under the `APP_CONFIG` _injection token_. +Thanks to these registrations, Angular can inject the `UserService` or the `HERO_DI_CONFIG` value +into any class that it creates. -Because the `HeroService` is used _only_ within the `HeroesComponent` -and its subcomponents, the top-level `HeroesComponent` is the ideal -place to register it. +
+You'll learn about _injection tokens_ and _provider_ syntax [below](#providers). +
-{@a register-providers-component} +{@a ngmodule-vs-comp} -### Registering providers in a component +### _@NgModule_ or _@Component_? -Here's a revised `HeroesComponent` that registers the `HeroService` in its `providers` array. +Should you register a service with an Angular module or with a component? +The two choices lead to differences in service _scope_ and service _lifetime_. +**Angular module providers** (`@NgModule.providers`) are registered with the application's root injector. +Angular can inject the corresponding services in any class it creates. +Once created, a service instance lives for the life of the app and Angular injects this one service instance in every class that needs it. - - - +You're likely to inject the `UserService` in many places throughout the app +and will want to inject the same service instance every time. +Providing the `UserService` with an Angular module is a good choice. +
+To be precise, Angular module providers are registered with the root injector +_unless the module is_ [lazy loaded](guide/ngmodule#lazy-load-DI). +In this sample, all modules are _eagerly loaded_ when the application starts, +so all module providers are registered with the app's root injector. -{@a ngmodule-vs-comp} +

+
-### When to use _NgModule_ versus an application component +**A component's providers** (`@Component.providers`) are registered with each component instance's own injector. -On the one hand, a provider in an `NgModule` is registered in the root injector. That means that every provider -registered within an `NgModule` will be accessible in the _entire application_. +Angular can only inject the corresponding services in that component instance or one of its descendant component instances. +Angular cannot inject the same service instance anywhere else. -On the other hand, a provider registered in an application component is available only on -that component and all its children. +Note that a component-provided service may have a limited lifetime. Each new instance of the component gets its own instance of the service +and, when the component instance is destroyed, so is that service instance. -Here, the `APP_CONFIG` service needs to be available all across the application, so it's -registered in the `AppModule` `@NgModule` `providers` array. -But since the `HeroService` is only used within the *Heroes* -feature area and nowhere else, it makes sense to register it in -the `HeroesComponent`. +In this sample app, the `HeroComponent` is created when the application starts +and is never destroyed so the `HeroService` created for the `HeroComponent` also live for the life of the app. +If you want to restrict `HeroService` access to the `HeroComponent` and its nested `HeroListComponent`, +providing the `HeroService` in the `HeroComponent` may be a good choice.
- - -Also see *"Should I add app-wide providers to the root `AppModule` or -the root `AppComponent`?"* in the [NgModule FAQ](guide/ngmodule-faq#q-root-component-or-module). - +The scope and lifetime of component-provided services is a consequence of [the way Angular creates component instances](#component-child-injectors).
+## Inject a service +The `HeroListComponent` should get heroes from the `HeroService`. -{@a prep-for-injection} +The component shouldn't create the `HeroService` with `new`. +It should ask for the `HeroService` to be injected. +You can tell Angular to inject a dependency in the component's constructor by specifying a **constructor parameter with the dependency type**. +Here's the `HeroListComponent` constructor, asking for the `HeroService` to be injected. -### Preparing the _HeroListComponent_ for injection - -The `HeroListComponent` should get heroes from the injected `HeroService`. -Per the dependency injection pattern, the component must ask for the service in its -constructor, [as discussed earlier](guide/dependency-injection#ctor-injection). -It's a small change: + + +Of course, the `HeroListComponent` should do something with the injected `HeroService`. +Here's the revised component, making use of the injected service, side-by-side with the previous version for comparison. - - - + - - + - +Notice that the `HeroListComponent` doesn't know where the `HeroService` comes from. +_You_ know that it comes from the parent `HeroesComponent`. +But if you decided instead to provide the `HeroService` in the `AppModule`, +the `HeroListComponent` wouldn't change at all. +The _only thing that matters_ is that the `HeroService` is provided in some parent injector. +{@a singleton-services} -
- - - -#### Focus on the constructor - -Adding a parameter to the constructor isn't all that's happening here. - - - - - - - - -Note that the constructor parameter has the type `HeroService`, and that -the `HeroListComponent` class has an `@Component` decorator -(scroll up to confirm that fact). -Also recall that the parent component (`HeroesComponent`) -has `providers` information for `HeroService`. - -The constructor parameter type, the `@Component` decorator, -and the parent's `providers` information combine to tell the -Angular injector to inject an instance of -`HeroService` whenever it creates a new `HeroListComponent`. - - -
- - - -{@a di-metadata} - - -### Implicit injector creation - -You saw how to use an injector to create a new -`Car` earlier in this guide. -You _could_ create such an injector -explicitly: - - - - - +## Singleton services +Services are singletons _within the scope of an injector_. +There is at most one instance of a service in a given injector. +There is only one root injector and the `UserService` is registered with that injector. +Therefore, there can be just one `UserService` instance in the entire app +and every class that injects `UserService` get this service instance. -You won't find code like that in the Tour of Heroes or any of the other -documentation samples. -You *could* write code that [explicitly creates an injector](guide/dependency-injection#explicit-injector) if you *had* to, -but it's not always the best choice. -Angular takes care of creating and calling injectors -when it creates components for you—whether through HTML markup, as in ``, -or after navigating to a component with the [router](guide/router). -If you let Angular do its job, you'll enjoy the benefits of automated dependency injection. +However, Angular DI is a +[hierarchical injection system](guide/hierarchical-dependency-injection), +which means that nested injectors can create their own service instances. +Angular creates nested injectors all the time. +{@a component-child-injectors} -{@a singleton-services} +## Component child injectors +For example, when Angular creates a new instance of a component that has `@Component.providers`, +it also creates a new _child injector_ for that instance. -### Singleton services +Component injectors are independent of each other and +each of them creates its own instances of the component-provided services. -Dependencies are singletons within the scope of an injector. -In this guide's example, a single `HeroService` instance is shared among the -`HeroesComponent` and its `HeroListComponent` children. +When Angular destroys one of these component instance, it also destroys the +component's injector and that injector's service instances. -However, Angular DI is a hierarchical injection -system, which means that nested injectors can create their own service instances. -For more information, see [Hierarchical Injectors](guide/hierarchical-dependency-injection). +Thanks to [injector inheritance](guide/hierarchical-dependency-injection), +you can still inject application-wide services into these components. +A component's injector is a child of its parent component's injector, +and a descendent of its parent's parent's injector, and so on all the way back to the application's _root_ injector. +Angular can inject a service provided by any injector in that lineage. +For example, Angular could inject a `HeroListComponent` +with both the `HeroService` provided in `HeroComponent` +and the `UserService` provided in `AppModule`. {@a testing-the-component} - -### Testing the component +## Testing the component Earlier you saw that designing a class for dependency injection makes the class easier to test. Listing dependencies as constructor parameters may be all you need to test application parts effectively. @@ -512,234 +268,132 @@ Listing dependencies as constructor parameters may be all you need to test appli For example, you can create a new `HeroListComponent` with a mock service that you can manipulate under test: - - - -
- - -Learn more in [Testing](guide/testing). - +Learn more in the [Testing](guide/testing) guide.
- - {@a service-needs-service} - -### When the service needs a service +## When the service needs a service The `HeroService` is very simple. It doesn't have any dependencies of its own. - What if it had a dependency? What if it reported its activities through a logging service? You'd apply the same *constructor injection* pattern, adding a constructor that takes a `Logger` parameter. -Here is the revision compared to the original. - +Here is the revised `HeroService` that injects the `Logger`, side-by-side with the previous service for comparison. - - +The constructor asks for an injected instance of a `Logger` and stores it in a private field called `logger`. +The `getHeroes()` method logs a message when asked to fetch heroes. -The constructor now asks for an injected instance of a `Logger` and stores it in a private property called `logger`. -You call that property within the `getHeroes()` method when anyone asks for heroes. - - -{@a injectable} - - -### Why _@Injectable()_? - -**[@Injectable()](api/core/Injectable)** marks a class as available to an -injector for instantiation. Generally speaking, an injector reports an -error when trying to instantiate a class that is not marked as -`@Injectable()`. - - -
- - - -As it happens, you could have omitted `@Injectable()` from the first -version of `HeroService` because it had no injected parameters. -But you must have it now that the service has an injected dependency. -You need it because Angular requires constructor parameter metadata -in order to inject a `Logger`. - - -
- +{@a logger-service} +#### The dependent _Logger_ service -
+The sample app's `Logger` service is quite simple: + + +If the app didn't provide this `Logger`, +Angular would throw an exception when it looked for a `Logger` to inject +into the `HeroService`. -
- Suggestion: add @Injectable() to every service class -
+ + ERROR Error: No provider for Logger! + +Because a singleton logger service is useful everywhere, +it's provided in the root `AppModule`. + + -Consider adding `@Injectable()` to every service class, even those that don't have dependencies -and, therefore, do not technically require it. Here's why: -
    +{@a injectable} -
  • - Future proofing: No need to remember @Injectable() when you add a dependency later. -
  • +## _@Injectable()_ -
  • - Consistency: All services follow the same rules, and you don't have to wonder why a decorator is missing. -
  • +The **[@Injectable()](api/core/Injectable)** decorator identifies a service class +that _might_ require injected dependencies. -
+The `HeroService` must be annotated with `@Injectable()` because it requires an injected `Logger`. +
+Always write `@Injectable()` with parentheses, not just `@Injectable`.
+When Angular creates a class whose constructor has parameters, +it looks for type and injection metadata about those parameters +so that it can inject the right service. +If Angular can't find that parameter information, it throws an error. -Injectors are also responsible for instantiating components -like `HeroesComponent`. So why doesn't `HeroesComponent` have -`@Injectable()`? - -You *can* add it if you really want to. It isn't necessary because the -`HeroesComponent` is already marked with `@Component`, and this -decorator class (like `@Directive` and `@Pipe`, which you learn about later) -is a subtype of [@Injectable()](api/core/Injectable). It is in -fact `@Injectable()` decorators that -identify a class as a target for instantiation by an injector. - +Angular can only find the parameter information _if the class has a decorator of some kind_. +While _any_ decorator will do, +the `@Injectable()` decorator is the standard decorator for service classes.
+The decorator requirement is imposed by TypeScript. +TypeScript normally discards parameter type information when it _transpiles_ the code to JavaScript. +It preserves this information if the class has a decorator +and the `emitDecoratorMetadata` compiler option is set `true` +in TypeScript's `tsconfig.json` configuration file, . - -At runtime, injectors can read class metadata in the transpiled JavaScript code -and use the constructor parameter type information -to determine what things to inject. - -Not every JavaScript class has metadata. -The TypeScript compiler discards metadata by default. -If the `emitDecoratorMetadata` compiler option is true -(as it should be in the `tsconfig.json`), -the compiler adds the metadata to the generated JavaScript -for _every class with at least one decorator_. - -While any decorator will trigger this effect, mark the service class with the -[@Injectable()](api/core/Injectable) decorator -to make the intent clear. - - -
- - - -
- - - -
- Always include the parentheses -
- - - -Always write `@Injectable()`, not just `@Injectable`. -The application will fail mysteriously if you forget the parentheses. - +The CLI configures `tsconfig.json` with `emitDecoratorMetadata: true` +It's your job to put `@Injectable()` on your service classes.
+The `Logger` service is annotated with `@Injectable()` decorator too, +although it has no constructor and no dependencies. -{@a logger-service} - -## Creating and registering a logger service - -Inject a logger into `HeroService` in two steps: - -1. Create the logger service. -1. Register it with the application. - -The logger service is quite simple: - - - - - - - - -You're likely to need the same logger service everywhere in your application, -so put it in the project's `app` folder and -register it in the `providers` array of the application module, `AppModule`. - - - - - - - - -If you forget to register the logger, Angular throws an exception when it first looks for the logger: - - - EXCEPTION: No provider for Logger! (HeroListComponent -> HeroService -> Logger) - - - - - -That's Angular telling you that the dependency injector couldn't find the *provider* for the logger. -It needed that provider to create a `Logger` to inject into a new -`HeroService`, which it needed to -create and inject into a new `HeroListComponent`. - -The chain of creations started with the `Logger` provider. *Providers* are the subject of the next section. +In fact, _every_ Angular service class in this app is annotated with the `@Injectable()` decorator, whether or not it has a constructor and dependencies. +`@Injectable()` is a required coding style for services. {@a providers} -## Injector providers +## Providers -A provider *provides* the concrete, runtime version of a dependency value. +A service provider *provides* the concrete, runtime version of a dependency value. The injector relies on **providers** to create instances of the services -that the injector injects into components and other services. - -You must register a service *provider* with the injector, or it won't know how to create the service. +that the injector injects into components, directives, pipes, and other services. -Earlier you registered the `Logger` service in the `providers` array of the metadata for the `AppModule` like this: +You must register a service *provider* with an injector, or it won't know how to create the service. +The next few sections explain the many ways you can specify a provider. - - - - +Almost all of the accompanying code snippets are extracts from the sample app's `providers.component.ts` file. +### The class as its own provider There are many ways to *provide* something that looks and behaves like a `Logger`. The `Logger` class itself is an obvious and natural provider. + + + + But it's not the only way. You can configure the injector with alternative providers that can deliver an object that behaves like a `Logger`. @@ -749,48 +403,29 @@ Any of these approaches might be a good choice under the right circumstances. What matters is that the injector has a provider to go to when it needs a `Logger`. +{@a provide} -
- -
- - - -### The *Provider* class and _provide_ object literal - +### The _provide_ object literal -You wrote the `providers` array like this: - - - +Here's the class-provider syntax again. + - - This is actually a shorthand expression for a provider registration using a _provider_ object literal with two properties: - - - + - - -The first is the [token](guide/dependency-injection#token) that serves as the key for both locating a dependency value +The `provide` property holds the [token](guide/dependency-injection#token) that serves as the key for both locating a dependency value and registering the provider. -The second is a provider definition object, +The second property is always a provider definition object, which you can think of as a *recipe* for creating the dependency value. There are many ways to create dependency values just as there are many ways to write a recipe. - -
- -
- - +{@a class-provider} ### Alternative class providers @@ -798,40 +433,27 @@ Occasionally you'll ask a different class to provide the service. The following code tells the injector to return a `BetterLogger` when something asks for the `Logger`. - - - + - - {@a class-provider-dependencies} - ### Class provider with dependencies + Maybe an `EvenBetterLogger` could display the user name in the log message. This logger gets the user from the injected `UserService`, which is also injected at the application level. - - - + - - Configure it like `BetterLogger`. - - - + - - {@a aliased-class-providers} - ### Aliased class providers Suppose an old component depends upon an `OldLogger` class. @@ -848,57 +470,34 @@ The `OldLogger` should be an alias for `NewLogger`. You certainly do not want two different `NewLogger` instances in your app. Unfortunately, that's what you get if you try to alias `OldLogger` to `NewLogger` with `useClass`. - - - + - - The solution: alias with the `useExisting` option. - - - - {@a value-provider} - ### Value providers - Sometimes it's easier to provide a ready-made object rather than ask the injector to create it from a class. - - - + - - Then you register a provider with the `useValue` option, which makes this object play the logger role. - - - - See more `useValue` examples in the [Non-class dependencies](guide/dependency-injection#non-class-dependencies) and [InjectionToken](guide/dependency-injection#injection-token) sections. - -
- -
- - +{@a factory-provider} ### Factory providers @@ -923,44 +522,29 @@ Unlike `EvenBetterLogger`, you can't inject the `UserService` into the `HeroServ The `HeroService` won't have direct access to the user information to decide who is authorized and who is not. - Instead, the `HeroService` constructor takes a boolean flag to control display of secret heroes. - - - - You can inject the `Logger`, but you can't inject the boolean `isAuthorized`. You'll have to take over the creation of new instances of this `HeroService` with a factory provider. A factory provider needs a factory function: - - - - Although the `HeroService` has no access to the `UserService`, the factory function does. You inject both the `Logger` and the `UserService` into the factory provider and let the injector pass them along to the factory function: - - - -
- - The `useFactory` field tells Angular that the provider is a factory function whose implementation is the `heroServiceFactory`. @@ -968,11 +552,8 @@ The `deps` property is an array of [provider tokens](guide/dependency-injection# The `Logger` and `UserService` classes serve as tokens for their own class providers. The injector resolves these tokens and injects the corresponding services into the matching factory function parameters. -
- - Notice that you captured the factory provider in an exported variable, `heroServiceProvider`. This extra step makes the factory provider reusable. You can register the `HeroService` with this variable wherever you need it. @@ -981,20 +562,16 @@ In this sample, you need it only in the `HeroesComponent`, where it replaces the previous `HeroService` registration in the metadata `providers` array. Here you see the new and the old implementation side-by-side: - - - - + - {@a token} ## Dependency injection tokens @@ -1007,85 +584,54 @@ In all previous examples, the dependency value has been a class *instance*, and the class *type* served as its own lookup key. Here you get a `HeroService` directly from the injector by supplying the `HeroService` type as the token: - - - - You have similar good fortune when you write a constructor that requires an injected class-based dependency. When you define a constructor parameter with the `HeroService` class type, Angular knows to inject the service associated with that `HeroService` class token: - - - - This is especially convenient when you consider that most dependency values are provided by classes. - {@a non-class-dependencies} - ### Non-class dependencies -

- What if the dependency value isn't a class? Sometimes the thing you want to inject is a - string, function, or object. -

- - - -

- Applications often define configuration objects with lots of small facts - (like the title of the application or the address of a web API endpoint) - but these configuration objects aren't always instances of a class. - They can be object literals such as this one: -

- +What if the dependency value isn't a class? Sometimes the thing you want to inject is a +string, function, or object. +Applications often define configuration objects with lots of small facts +(like the title of the application or the address of a web API endpoint) +but these configuration objects aren't always instances of a class. +They can be object literals such as this one: - - + - - What if you'd like to make this configuration object available for injection? You know you can register an object with a [value provider](guide/dependency-injection#value-provider). - But what should you use as the token? You don't have a class to serve as a token. There is no `AppConfig` class. -
- - ### TypeScript interfaces aren't valid tokens -The `HERO_DI_CONFIG` constant has an interface, `AppConfig`. Unfortunately, you -cannot use a TypeScript interface as a token: - - +The `HERO_DI_CONFIG` constant conforms to the `AppConfig` interface. +Unfortunately, you cannot use a TypeScript interface as a token: + - - - - + - - That seems strange if you're used to dependency injection in strongly typed languages, where an interface is the preferred dependency lookup key. @@ -1093,70 +639,45 @@ It's not Angular's doing. An interface is a TypeScript design-time artifact. Jav The TypeScript interface disappears from the generated JavaScript. There is no interface type information left for Angular to find at runtime. -
- - {@a injection-token} - ### _InjectionToken_ One solution to choosing a provider token for non-class dependencies is to define and use an [*InjectionToken*](api/core/InjectionToken). The definition of such a token looks like this: - - - - The type parameter, while optional, conveys the dependency's type to developers and tooling. The token description is another developer aid. Register the dependency provider using the `InjectionToken` object: - - - + - - Now you can inject the configuration object into any constructor that needs it, with the help of an `@Inject` decorator: - - - -
- - Although the `AppConfig` interface plays no role in dependency injection, it supports typing of the configuration object within the class. -
- - Alternatively, you can provide and inject the configuration object in an ngModule like `AppModule`. - - -
- -
- + +{@a optional} ## Optional dependencies @@ -1165,25 +686,16 @@ a `logger`? You can tell Angular that the dependency is optional by annotating the constructor argument with `@Optional()`: - - - - - - - When using `@Optional()`, your code must be prepared for a null value. If you don't register a `logger` somewhere up the line, the injector will set the value of `logger` to null. - - ## Summary You learned the basics of Angular dependency injection in this page. @@ -1203,13 +715,9 @@ nested injectors, in Developers rarely work directly with an injector, but here's an `InjectorComponent` that does. - - - - An `Injector` is itself an injectable service. In this example, Angular injects the component's own `Injector` into the component's constructor. @@ -1245,7 +753,7 @@ must acquire services generically and dynamically. {@a one-class-per-file} -## Appendix: Why have one class per file +## Appendix: one class per file Having multiple classes in the same file is confusing and best avoided. Developers expect one class per file. Keep them happy. @@ -1259,12 +767,10 @@ you'll get a runtime null reference error.
- - You actually can define the component first with the help of the `forwardRef()` method as explained in this [blog post](http://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html). -But why flirt with trouble? -Avoid the problem altogether by defining components and services in separate files. + +But it's best to avoid the problem altogether by defining components and services in separate files.
diff --git a/aio-ja/content/guide/displaying-data.md b/aio-ja/content/guide/displaying-data.md index 432736bf03..c5a11d6edc 100644 --- a/aio-ja/content/guide/displaying-data.md +++ b/aio-ja/content/guide/displaying-data.md @@ -31,9 +31,11 @@ The easiest way to display a component property is to bind the property name through interpolation. With interpolation, you put the property name in the view template, enclosed in double curly braces: `{{myHero}}`. -Follow the [setup](guide/setup) instructions for creating a new project +Follow the [quickstart](guide/quickstart) instructions for creating a new project named displaying-data. +Delete the app.component.html file. It is not needed for this example. + Then modify the app.component.ts file by changing the template and the body of the component. @@ -48,7 +50,7 @@ When you're done, it should look like this: You added two properties to the formerly empty component: `title` and `myHero`. -The revised template displays the two component properties using double curly brace +The template displays the two component properties using double curly brace interpolation: @@ -92,7 +94,7 @@ the view, such as a keystroke, a timer completion, or a response to an HTTP requ Notice that you don't call **new** to create an instance of the `AppComponent` class. Angular is creating an instance for you. How? -The CSS `selector` in the `@Component` decorator specifies an element named ``. +The CSS `selector` in the `@Component` decorator specifies an element named ``. That element is a placeholder in the body of your `index.html` file: @@ -102,9 +104,9 @@ That element is a placeholder in the body of your `index.html` file: -When you bootstrap with the `AppComponent` class (in main.ts), Angular looks for a `` +When you bootstrap with the `AppComponent` class (in main.ts), Angular looks for a `` in the `index.html`, finds it, instantiates an instance of `AppComponent`, and renders it -inside the `` tag. +inside the `` tag. Now run the app. It should display the title and hero name: @@ -131,13 +133,23 @@ is simpler without the additional HTML file. In either style, the template data bindings have the same access to the component's properties. +
+ + By default, the Angular CLI generates components with a template file. You can override that with: + + + ng generate component hero -it + + +
+ ## Constructor or variable initialization? -Although this example uses variable assignment to initialize the components, you can instead declare and initialize the properties using a constructor: +Although this example uses variable assignment to initialize the components, you could instead declare and initialize the properties using a constructor: - + @@ -231,12 +243,16 @@ At the moment, the binding is to an array of strings. In real applications, most bindings are to more specialized objects. To convert this binding to use specialized objects, turn the array -of hero names into an array of `Hero` objects. For that you'll need a `Hero` class. +of hero names into an array of `Hero` objects. For that you'll need a `Hero` class: + + + ng generate class hero + -Create a new file in the `app` folder called `hero.ts` with the following code: +With the following code: - + diff --git a/aio-ja/content/guide/form-validation.md b/aio-ja/content/guide/form-validation.md index a01d861425..f154e27178 100644 --- a/aio-ja/content/guide/form-validation.md +++ b/aio-ja/content/guide/form-validation.md @@ -40,7 +40,7 @@ Note the following: also carries a custom validator directive, `forbiddenName`. For more information, see [Custom validators](guide/form-validation#custom-validators) section. -* `#name="ngModel"` exports `NgModel` into a local variable callled `name`. `NgModel` mirrors many of the properties of its underlying +* `#name="ngModel"` exports `NgModel` into a local variable called `name`. `NgModel` mirrors many of the properties of its underlying `FormControl` instance, so you can use this in the template to check for control states such as `valid` and `dirty`. For a full list of control properties, see the [AbstractControl](api/forms/AbstractControl) API reference. diff --git a/aio-ja/content/guide/forms.md b/aio-ja/content/guide/forms.md index 8731b34d73..94e337c0a2 100644 --- a/aio-ja/content/guide/forms.md +++ b/aio-ja/content/guide/forms.md @@ -29,19 +29,13 @@ You can run the in Plunker and download the code f You can build forms by writing templates in the Angular [template syntax](guide/template-syntax) with the form-specific directives and techniques described in this page. -
- - -You can also use a reactive (or model-driven) approach to build forms. -However, this page focuses on template-driven forms. - + You can also use a reactive (or model-driven) approach to build forms. + However, this page focuses on template-driven forms.
- - You can build almost any form with an Angular template—login forms, contact forms, and pretty much any business form. You can lay out the controls creatively, bind them to data, specify validation rules and display validation errors, conditionally enable or disable specific controls, trigger built-in visual feedback, and much more. @@ -51,13 +45,10 @@ otherwise wrestle with yourself. You'll learn to build a template-driven form that looks like this: -
Clean Form
- - The *Hero Employment Agency* uses this form to maintain personal information about heroes. Every hero needs a job. It's the company mission to match the right hero with the right crisis. @@ -65,27 +56,18 @@ Two of the three fields on this form are required. Required fields have a green If you delete the hero name, the form displays a validation error in an attention-grabbing style: -
Invalid, Name Required
- - Note that the *Submit* button is disabled, and the "required" bar to the left of the input control changes from green to red. -
- - -You can customize the colors and location of the "required" bar with standard CSS. - + You can customize the colors and location of the "required" bar with standard CSS.
- - You'll build this form in small steps: 1. Create the `Hero` model class. @@ -98,11 +80,15 @@ You'll build this form in small steps: 1. Handle form submission with *ngSubmit*. 1. Disable the form’s *Submit* button until the form is valid. - ## Setup -Follow the [setup](guide/setup) instructions for creating a new project -named angular-forms. +Create a new project named angular-forms: + + + + ng new angular-forms + + ## Create the Hero model class @@ -113,14 +99,19 @@ A model can be as simple as a "property bag" that holds facts about a thing of a That describes well the `Hero` class with its three required fields (`id`, `name`, `power`) and one optional field (`alterEgo`). -In the `app` directory, create the following file with the given content: +Using the Angular CLI, generate a new class named `Hero`: + - + ng generate class Hero +With this content: + + + It's an anemic model with few requirements and no behavior. Perfect for the demo. @@ -131,28 +122,29 @@ The `alterEgo` is optional, so the constructor lets you omit it; note the questi You can create a new hero like this: - - + - - - ## Create a form component An Angular form has two parts: an HTML-based _template_ and a component _class_ to handle data and user interactions programmatically. Begin with the class because it states, in brief, what the hero editor can do. -Create the following file with the given content: +Using the Angular CLI, generate a new component named `HeroForm`: + - + ng generate component HeroForm +With this content: + + + There’s nothing special about this component, nothing form-specific, nothing to distinguish it from any component you've written before. @@ -173,21 +165,6 @@ parent component. This is not a concern now and these future changes won't affec * You added a `diagnostic` property to return a JSON representation of the model. It'll help you see what you're doing during development; you've left yourself a cleanup note to discard it later. -### Why the separate template file? - -Why don't you write the template inline in the component file as you often do elsewhere? - -There is no "right" answer for all occasions. Inline templates are useful when they are short. -Most form templates aren't short. TypeScript and JavaScript files generally aren't the best place to -write (or read) large stretches of HTML, and few editors help with files that have a mix of HTML and code. - -Form templates tend to be large, even when displaying a small number of fields, -so it's usually best to put the HTML template in a separate file. -You'll write that template file in a moment. First, -revise the `app.module.ts` and `app.component.ts` to make use of the new `HeroFormComponent`. - - - ## Revise *app.module.ts* `app.module.ts` defines the application's root module. In it you identify the external modules you'll use in the application @@ -196,89 +173,57 @@ and declare the components that belong to this module, such as the `HeroFormComp Because template-driven forms are in their own module, you need to add the `FormsModule` to the array of `imports` for the application module before you can use forms. -Replace the contents of the "QuickStart" version with the following: +Update it with the following: - - - -
+ There are two changes: + 1. You import `FormsModule`. -There are three changes: - -1. You import `FormsModule` and the new `HeroFormComponent`. - -1. You add the `FormsModule` to the list of `imports` defined in the `@NgModule` decorator. This gives the application -access to all of the template-driven forms features, including `ngModel`. - -1. You add the `HeroFormComponent` to the list of `declarations` defined in the `@NgModule` decorator. This makes -the `HeroFormComponent` component visible throughout this module. - + 1. You add the `FormsModule` to the list of `imports` defined in the `@NgModule` decorator. This gives the application + access to all of the template-driven forms features, including `ngModel`.
- -
- - -If a component, directive, or pipe belongs to a module in the `imports` array, ​_don't_​ re-declare it in the `declarations` array. -If you wrote it and it should belong to this module, ​_do_​ declare it in the `declarations` array. - + If a component, directive, or pipe belongs to a module in the `imports` array, ​_don't_​ re-declare it in the `declarations` array. + If you wrote it and it should belong to this module, ​_do_​ declare it in the `declarations` array.
- - - -## Revise *app.component.ts* +## Revise *app.component.html* `AppComponent` is the application's root component. It will host the new `HeroFormComponent`. -Replace the contents of the "QuickStart" version with the following: +Replace the contents of its template with the following: - - + - - - -
- - -There are only two changes. -The `template` is simply the new element tag identified by the component's `selector` property. -This displays the hero form when the application component is loaded. -You've also dropped the `name` field from the class body. - + There are only two changes. + The `template` is simply the new element tag identified by the component's `selector` property. + This displays the hero form when the application component is loaded. + Don't forget to remove the `name` field from the class body as well.
- - - ## Create an initial HTML form template -Create the template file with the following contents: +Update the template file with the following contents: - - + - - The language is simply HTML5. You're presenting two of the `Hero` fields, `name` and `alterEgo`, and opening them up for user input in input boxes. @@ -289,52 +234,34 @@ You added a *Submit* button at the bottom with some classes on it for styling. *You're not using Angular yet*. There are no bindings or extra directives, just layout. -
- - -In template driven forms, if you've imported `FormsModule`, you don't have to do anything -to the `
` tag in order to make use of `FormsModule`. Continue on to see how this works. - + In template driven forms, if you've imported `FormsModule`, you don't have to do anything + to the `` tag in order to make use of `FormsModule`. Continue on to see how this works.
- - The `container`, `form-group`, `form-control`, and `btn` classes come from [Twitter Bootstrap](http://getbootstrap.com/css/). These classes are purely cosmetic. Bootstrap gives the form a little style. -
+
+ Angular forms don't require a style library +
- -
- Angular forms don't require a style library -
- - - -Angular makes no use of the `container`, `form-group`, `form-control`, and `btn` classes or -the styles of any external library. Angular apps can use any CSS library or none at all. - + Angular makes no use of the `container`, `form-group`, `form-control`, and `btn` classes or + the styles of any external library. Angular apps can use any CSS library or none at all.
+To add the stylesheet, open `styles.css` and add the following import line at the top: - -To add the stylesheet, open `index.html` and add the following link to the ``: - - - + - - - ## Add powers with _*ngFor_ The hero must choose one superpower from a fixed list of agency-approved powers. @@ -346,13 +273,10 @@ a technique seen previously in the [Displaying Data](guide/displaying-data) page Add the following HTML *immediately below* the *Alter Ego* group: - - + - - This code repeats the `