`,
+ providers: [HeroService]
+})
+export class SortedHeroesComponent extends HeroesBaseComponent {
+ constructor(heroService: HeroService) {
+ super(heroService);
+ }
+
+ protected _afterGetHeroes() {
+ this.heroes = this.heroes.sort((h1, h2) => {
+ return h1.name < h2.name ? -1 :
+ (h1.name > h2.name ? 1 : 0);
+ });
+ }
+}
+// #enddocregion sorted-heroes
diff --git a/public/docs/_examples/cb-dependency-injection/ts/app/user-context.service.ts b/public/docs/_examples/cb-dependency-injection/ts/app/user-context.service.ts
new file mode 100644
index 0000000000..b241675d31
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/app/user-context.service.ts
@@ -0,0 +1,32 @@
+// #docplaster
+// #docregion
+import {Injectable} from 'angular2/core';
+import {LoggerService} from './logger.service';
+import {UserService} from './user.service';
+
+// #docregion injectables, injectable
+@Injectable()
+export class UserContextService {
+// #enddocregion injectables, injectable
+ name:string;
+ role:string;
+ loggedInSince:Date;
+
+ // #docregion ctor, injectables
+ constructor(private _userService:UserService, private _loggerService:LoggerService){
+ // #enddocregion ctor, injectables
+ this.loggedInSince = new Date();
+ // #docregion ctor, injectables
+ }
+ // #enddocregion ctor, injectables
+
+ loadUser(userId:number){
+ let user = this._userService.getUserById(userId);
+ this.name = user.name;
+ this.role = user.role;
+
+ this._loggerService.logDebug('loaded User');
+ }
+// #docregion injectables, injectable
+}
+// #enddocregion injectables, injectable
diff --git a/public/docs/_examples/cb-dependency-injection/ts/app/user.service.ts b/public/docs/_examples/cb-dependency-injection/ts/app/user.service.ts
new file mode 100644
index 0000000000..f2d44d7a26
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/app/user.service.ts
@@ -0,0 +1,10 @@
+// #docregion
+import {Injectable} from 'angular2/core';
+
+@Injectable()
+export class UserService {
+
+ getUserById(userId:number):any{
+ return {name:'Bombasto',role:'Admin'};
+ }
+}
\ No newline at end of file
diff --git a/public/docs/_examples/cb-dependency-injection/ts/example-config.json b/public/docs/_examples/cb-dependency-injection/ts/example-config.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/cb-dependency-injection/ts/index.html b/public/docs/_examples/cb-dependency-injection/ts/index.html
new file mode 100644
index 0000000000..66db40eb30
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/index.html
@@ -0,0 +1,44 @@
+
+
+
+
+ Dependency Injection
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading app...
+
+
+
diff --git a/public/docs/_examples/cb-dependency-injection/ts/plnkr.json b/public/docs/_examples/cb-dependency-injection/ts/plnkr.json
new file mode 100644
index 0000000000..d20b01cf1d
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/plnkr.json
@@ -0,0 +1,9 @@
+{
+ "description": "Dependency Injection",
+ "files":[
+ "!**/*.d.ts",
+ "!**/*.js",
+ "!**/*.[1].*"
+ ],
+ "tags":["cookbook"]
+}
\ No newline at end of file
diff --git a/public/docs/_examples/cb-dependency-injection/ts/sample.css b/public/docs/_examples/cb-dependency-injection/ts/sample.css
new file mode 100644
index 0000000000..a8b59efd05
--- /dev/null
+++ b/public/docs/_examples/cb-dependency-injection/ts/sample.css
@@ -0,0 +1,26 @@
+.di-component{
+ padding: 10px;
+ width:300px;
+ margin-bottom: 10px;
+}
+div[myHighlight] {
+ padding: 2px 8px;
+}
+
+/* Parent Finder */
+.a, .b, .c {
+ margin: 6px 2px 6px;
+ padding: 4px 6px;
+}
+.a {
+ border: solid 2px black;
+}
+.b {
+ background: lightblue;
+ border: solid 1px darkblue;
+ display: flex;
+}
+.c {
+ background: pink;
+ border: solid 1px red;
+}
\ No newline at end of file
diff --git a/public/docs/_examples/package.json b/public/docs/_examples/package.json
index 73e8969a00..0c6772d3a2 100644
--- a/public/docs/_examples/package.json
+++ b/public/docs/_examples/package.json
@@ -4,7 +4,7 @@
"description": "Master package.json, the superset of all dependencies for all of the _example package.json files.",
"main": "index.js",
"scripts": {
- "start": "concurrently \"npm run tsc:w\" \"npm run lite\" ",
+ "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
"tsc": "tsc",
"tsc:w": "tsc -w",
"lite": "lite-server",
diff --git a/public/docs/_examples/quickstart/ts/package.1.json b/public/docs/_examples/quickstart/ts/package.1.json
index f399545abd..ad596c2088 100644
--- a/public/docs/_examples/quickstart/ts/package.1.json
+++ b/public/docs/_examples/quickstart/ts/package.1.json
@@ -2,7 +2,7 @@
"name": "angular2-quickstart",
"version": "1.0.0",
"scripts": {
- "start": "concurrently \"npm run tsc:w\" \"npm run lite\" ",
+ "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
"tsc": "tsc",
"tsc:w": "tsc -w",
"lite": "lite-server",
diff --git a/public/docs/_examples/tslint.json b/public/docs/_examples/tslint.json
new file mode 100644
index 0000000000..276453f4f5
--- /dev/null
+++ b/public/docs/_examples/tslint.json
@@ -0,0 +1,93 @@
+{
+ "rules": {
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "curly": true,
+ "eofline": true,
+ "forin": true,
+ "indent": [
+ true,
+ "spaces"
+ ],
+ "label-position": true,
+ "label-undefined": true,
+ "max-line-length": [
+ true,
+ 140
+ ],
+ "member-access": false,
+ "member-ordering": [
+ true,
+ "static-before-instance",
+ "variables-before-functions"
+ ],
+ "no-arg": true,
+ "no-bitwise": true,
+ "no-console": [
+ true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-construct": true,
+ "no-debugger": true,
+ "no-duplicate-key": true,
+ "no-duplicate-variable": true,
+ "no-empty": false,
+ "no-eval": true,
+ "no-inferrable-types": true,
+ "no-shadowed-variable": true,
+ "no-string-literal": false,
+ "no-switch-case-fall-through": true,
+ "no-trailing-whitespace": true,
+ "no-unused-expression": true,
+ "no-unused-variable": true,
+ "no-unreachable": true,
+ "no-use-before-declare": true,
+ "no-var-keyword": true,
+ "object-literal-sort-keys": false,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-catch",
+ "check-else",
+ "check-whitespace"
+ ],
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "radix": true,
+ "semicolon": [
+ "always"
+ ],
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "typedef-whitespace": [
+ true,
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "variable-name": false,
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ]
+ }
+}
diff --git a/public/docs/dart/latest/cookbook/_data.json b/public/docs/dart/latest/cookbook/_data.json
index 4d4757ee57..ce8315d497 100644
--- a/public/docs/dart/latest/cookbook/_data.json
+++ b/public/docs/dart/latest/cookbook/_data.json
@@ -17,7 +17,13 @@
"intro": "Share information between different directives and components"
},
- "dynamic-form": {
+ "dependency-injection": {
+ "title": "Dependency Injection",
+ "intro": "Techniques for Dependency Injection",
+ "hide": true
+ },
+
+ "dynamic-forms": {
"title": "Dynamic Form",
"intro": "Render dynamic forms with NgFormModel",
"hide": true
diff --git a/public/docs/dart/latest/cookbook/dependency-injection.jade b/public/docs/dart/latest/cookbook/dependency-injection.jade
new file mode 100644
index 0000000000..f8df2a84a6
--- /dev/null
+++ b/public/docs/dart/latest/cookbook/dependency-injection.jade
@@ -0,0 +1 @@
+!= partial("../../../_includes/_ts-temp")
\ No newline at end of file
diff --git a/public/docs/js/latest/cookbook/_data.json b/public/docs/js/latest/cookbook/_data.json
index dc91a7b4a2..a2040caccf 100644
--- a/public/docs/js/latest/cookbook/_data.json
+++ b/public/docs/js/latest/cookbook/_data.json
@@ -16,10 +16,14 @@
"intro": "Share information between different directives and components"
},
- "dynamic-form": {
+ "dependency-injection": {
+ "title": "Dependency Injection",
+ "intro": "Techniques for Dependency Injection"
+ },
+
+ "dynamic-forms": {
"title": "Dynamic Form",
- "intro": "Render dynamic forms with NgFormModel",
- "hide": true
+ "intro": "Render dynamic forms with NgFormModel"
},
"ts-to-js": {
diff --git a/public/docs/js/latest/cookbook/dependency-injection.jade b/public/docs/js/latest/cookbook/dependency-injection.jade
new file mode 100644
index 0000000000..f8df2a84a6
--- /dev/null
+++ b/public/docs/js/latest/cookbook/dependency-injection.jade
@@ -0,0 +1 @@
+!= partial("../../../_includes/_ts-temp")
\ No newline at end of file
diff --git a/public/docs/ts/latest/cookbook/_data.json b/public/docs/ts/latest/cookbook/_data.json
index fe2f7b8954..e4363318ef 100644
--- a/public/docs/ts/latest/cookbook/_data.json
+++ b/public/docs/ts/latest/cookbook/_data.json
@@ -16,6 +16,11 @@
"intro": "Share information between different directives and components"
},
+ "dependency-injection": {
+ "title": "Dependency Injection",
+ "intro": "Techniques for Dependency Injection"
+ },
+
"dynamic-form": {
"title": "Dynamic Form",
"intro": "Render dynamic forms with NgFormModel"
diff --git a/public/docs/ts/latest/cookbook/dependency-injection.jade b/public/docs/ts/latest/cookbook/dependency-injection.jade
new file mode 100644
index 0000000000..c5fdcd0a7c
--- /dev/null
+++ b/public/docs/ts/latest/cookbook/dependency-injection.jade
@@ -0,0 +1,908 @@
+include ../_util-fns
+
+:marked
+ Dependency Injection is a powerful pattern for managing code dependencies.
+ In this cookbook we will explore many of the features of Dependency Injection (DI) in Angular.
+
+
+:marked
+ ## Table of contents
+
+ [Application-wide dependencies](#app-wide-dependencies)
+
+ [External module configuration](#external-module-configuration)
+
+ [*@Injectable* and nested service dependencies](#nested-dependencies)
+
+ [Limit service scope to a component subtree](#service-scope)
+
+ [Multiple service instances (sandboxing)](#multiple-service-instances)
+
+ [Qualify dependency lookup with *@Optional* and *@Host*](#qualify-dependency-lookup)
+
+ [Inject the component's DOM element](#component-element)
+
+ [Define dependencies with providers](#providers)
+ * [The *provide* function](#provide)
+ * [useValue - the *value provider*](#usevalue)
+ * [useClass - the *class provider*](#useclass)
+ * [useExisting - the *alias provider*](#useexisting)
+ * [useFactory - the *factory provider*](#usefactory)
+
+ [Provider token alternatives](#tokens)
+ * [class-interface](#class-interface)
+ * [OpaqueToken](#opaque-token)
+
+ [Inject into a derived class](#di-inheritance)
+
+ [Find a parent component by injection](#find-parent)
+ * [Find parent with a known component type](#known-parent)
+ * [Cannot find a parent by its base class](#base-parent)
+ * [Find a parent by its class-interface](#class-interface-parent)
+ * [Find a parent in a tree of parents (*@SkipSelf*)](#parent-tree)
+ * [A *provideParent* helper function](#provideparent)
+
+ [Break circularities with a forward class reference (*forwardRef*)](#forwardref)
+
+:marked
+ **See the [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)**
+ of the code supporting this cookbook.
+
+.l-main-section
+
+
+:marked
+ ## Application-wide dependencies
+ Register providers for dependencies used throughout the application in the root application component, `AppComponent`.
+
+ In the following example, we import and register several services
+ (the `LoggerService`, `UserContext`, and the `UserService`)
+ in the `@Component` metadata `providers` array.
+
++makeExample('cb-dependency-injection/ts/app/app.component.ts','import-services','app/app.component.ts (excerpt)')(format='.')
+:marked
+ All of these services are implemented as classes.
+ Service classes can act as their own providers which is why listing them in the `providers` array
+ is all the registration we need.
+.l-sub-section
+ :marked
+ A *provider* is something that can create or deliver a service.
+ Angular creates a service instance from a class provider by "new-ing" it.
+ Learn more about providers [below](#providers).
+:marked
+ Now that we've registered these services,
+ Angular can inject them into the constructor of *any* component or service, *anywhere* in the application.
++makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','ctor','app/hero-bios.component.ts (component constructor injection)')(format='.')
+
++makeExample('cb-dependency-injection/ts/app/user-context.service.ts','ctor','app/user-context.service.ts (service constructor injection)')(format='.')
+
+
+.l-main-section
+:marked
+ ## External module configuration
+ We can register _certain_ module providers when bootstrapping rather than in the root application component.
+
+ We'd do this when we expect to select or configure external modules that support our application
+ but (a) aren't conceptually part of the application and (b) that we could change later without
+ altering the essential logic of the application.
+
+ For example, we might configure the Component Router with different
+ [location strategies](../guide/router.html#location-strategy) based on environmental factors.
+ The choice of location strategy doesn't matter to the application itself.
+
+ We could sneak in a fake HTTP backend with sample data during development rather than
+ allow http calls to a remote server (that might not yet exist).
+ We'll switch to the real backend in production.
+ The application shouldn't know or care one way or the other.
+
+ See both examples in the following `main.ts`
+ where we list their service providers in an array in the second parameter of the `bootstrap` method.
+
++makeExample('cb-dependency-injection/ts/app/main.ts','bootstrap','app/main.ts')(format='.')
+
+a(id="injectable")
+a(id="nested-dependencies")
+.l-main-section
+:marked
+ ## *@Injectable* and nested service dependencies
+ The consumer of an injected service does not know how to create that service.
+ It shouldn't care.
+ It's the dependency injection's job to create and cache that service.
+
+ Sometimes a service depends on other services ... which may depend on yet other services.
+ Resolving these nested dependencies in the correct order is also the framework's job.
+ At each step, the consumer of dependencies simply declares what it requires in its constructor and the framework takes over.
+
+ For example, we inject both the `LoggerService` and the `UserContext` in the `AppComponent`.
++makeExample('cb-dependency-injection/ts/app/app.component.ts','ctor','app/app.component.ts')(format='.')
+
+:marked
+ The `UserContext` in turn has dependencies on both the `LoggerService` (again) and
+ a `UserService` that gathers information about a particular user.
+
++makeExample('cb-dependency-injection/ts/app/user-context.service.ts','injectables','user-context.service.ts (injection)')(format='.')
+
+:marked
+ When Angular creates an`AppComponent`, the dependency injection framework creates an instance of the `LoggerService` and
+ starts to create the `UserContextService`.
+ The `UserContextService` needs the `LoggerService`, which the framework already has, and the `UserService`, which it has yet to create.
+ The `UserService` has no dependencies so the dependency injection framework can just `new` one into existence.
+
+ The beauty of dependency injection is that the author of `AppComponent` didn't care about any of this.
+ The author simply declared what was needed in the constructor (`LoggerService` and `UserContextService`) and the framework did the rest.
+
+ Once all the dependencies are in place, the `AppComponent` displays the user information:
+
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/logged-in-user.png" alt="Logged In User")
+:marked
+ ### *@Injectable()*
+ Notice the `@Injectable()`decorator on the `UserContextService` class.
++makeExample('cb-dependency-injection/ts/app/user-context.service.ts','injectable','user-context.service.ts (@Injectable)')(format='.')
+:marked
+ That decorator makes it possible for Angular to identify the types of its two dependencies, `LoggerService` and `UserService`.
+
+ Technically, the `@Injectable()`decorator is only _required_ for a service class that has _its own dependencies_.
+ The `LoggerService` doesn't depend on anything. The logger would work if we omitted `@Injectable()`
+ and the generated code would be slightly smaller.
+
+ But the service would break the moment we gave it a dependency and we'd have to go back and
+ and add `@Injectable()` to fix it. We add `@Injectable()` from the start for the sake of consistency and to avoid future pain.
+
+.alert.is-helpful
+ :marked
+ Although we recommend applying `@Injectable` to all service classes, do not feel bound by it.
+ Some developers prefer to add it only where needed and that's a reasonable policy too.
+
+.l-sub-section
+ :marked
+ The `AppComponent` class had two dependencies as well but no `@Injectable()`.
+ It didn't need `@Injectable()` because that component class has the `@Component` decorator.
+ In Angular with TypeScript, a *single* decorator — *any* decorator — is sufficient to identify dependency types.
+
+
+
+.l-main-section
+:marked
+ ## Limit service scope to a component subtree
+
+ All injected service dependencies are singletons meaning that,
+ for a given dependency injector ("injector"), there is only one instance of service.
+
+ But an Angular application has multiple dependency injectors, arranged in a tree hierarchy that parallels the component tree.
+ So a particular service can be *provided* (and created) at any component level and multiple times
+ if provided in multiple components.
+
+ By default, a service dependency provided in one component is visible to all of its child components and
+ Angular injects the same service instance into all child components that ask for that service.
+
+ Accordingly, dependencies provided in the root `AppComponent` can be injected into *any* component *anywhere* in the application.
+
+ That isn't always desireable.
+ Sometimes we want to restrict service availability to a particular region of the application.
+
+ We can limit the scope of an injected service to a *branch* of the application hierarchy
+ by providing that service *at the sub-root component for that branch*.
+ Here we provide the `HeroService` to the `HeroesBaseComponent` by listing it in the `providers` array:
++makeExample('cb-dependency-injection/ts/app/sorted-heroes.component.ts','injection','app/sorted-heroes.component.ts (HeroesBaseComponent excerpt)')
+:marked
+ When Angular creates the `HeroesBaseComponent`, it also creates a new instance of `HeroService`
+ that is visible only to the component and its children (if any).
+
+ We could also provide the `HeroService` to a *different* component elsewhere in the application.
+ That would result in a *different* instance of the service, living in a *different* injector.
+.l-sub-section
+ :marked
+ We examples of such scoped `HeroService` singletons appear throughout the accompanying sample code,
+ including the `HeroBiosComponent`, `HeroOfTheMonthComponent`, and `HeroesBaseComponent`.
+ Each of these components has its own `HeroService` instance managing its own independent collection of heroes.
+
+.l-main-section
+.alert.is-helpful
+ :marked
+ ### Take a break!
+ This much Dependency Injection knowledge may be all that many Angular developers
+ ever need to build their applications. It doesn't always have to be more complicated.
+
+
+.l-main-section
+:marked
+ ## Multiple service instances (sandboxing)
+
+ Sometimes we want multiple instances of a service at *the same level of the component hierarchy*.
+
+ A good example is a service that holds state for its companion component instance.
+ We need a separate instance of the service for each component.
+ Each service has its own work-state, isolated from the service-and-state of a different component.
+ We call this *sandboxing* because each service and component instance has its own sandbox to play in.
+
+
+ Imagine a `HeroBiosComponent` that presents three instances of the `HeroBioComponent`.
++makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','simple','ap/hero-bios.component.ts')
+:marked
+ Each `HeroBioComponent` can edit a single hero's biography.
+ A `HeroBioComponent` relies on a `HeroCacheService` to fetch, cache, and perform other persistence operations on that hero.
++makeExample('cb-dependency-injection/ts/app/hero-cache.service.ts','service','app/hero-cache.service.ts')
+:marked
+ Clearly the three instances of the `HeroBioComponent` can't share the same `HeroCacheService`.
+ They'd be competing with each other to determine which hero to cache.
+
+ Each `HeroBioComponent` gets its *own* `HeroCacheService` instance
+ by listing the `HeroCacheService` in its metadata `providers` array.
++makeExample('cb-dependency-injection/ts/app/hero-bio.component.ts','component','app/hero-bio.component.ts')
+:marked
+ The parent `HeroBiosComponent` binds a value to the `heroId`.
+ The `ngOnInit` pass that `id` to the service which fetches and caches the hero.
+ The getter for the `hero` property pulls the cached hero from the service.
+ And the template displays this data-bound property.
+
+ Find this example in [live code](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)
+ and confirm that the three `HeroBioComponent` instances have their own cached hero data.
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/hero-bios.png" alt="Bios")
+
+a(id="optional")
+a(id="qualify-dependency-lookup")
+.l-main-section
+:marked
+ ## Qualify dependency lookup with *@Optional* and *@Host*
+ We learned that dependencies can be registered at any level in the component hierarchy.
+
+ When a component requests a dependency, Angular starts with that component's injector and walks up the injector tree
+ until it finds the first suitable provider. Angular throws an error if it can't find the dependency during that walk.
+
+ We *want* this behavior most of the time.
+ But sometimes we need to limit the search and/or accommodate a missing dependency.
+ We can modify Angular's search behavior with the `@Host` and `@Optional` qualifying decorators,
+ used individually or together.
+
+ The `@Optional` decorator tells Angular to continue when it can't find the dependency.
+ Angular sets the injection parameter to `null` instead.
+
+ The `@Host` decorator stops the upward search at the *host component*.
+
+ The host component is typically the component requesting the dependency.
+ But when this component is projected into a *parent* component, that parent component becomes the host.
+ We look at this second, more interesting case in our next example.
+
+ ### Demonstration
+ The `HeroBiosAndContactsComponent` is a revision of the `HeroBiosComponent` that we looked at [above](#hero-bios-component).
++makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','hero-bios-and-contacts','app/hero-bios.component.ts (HeroBiosAndContactsComponent)')
+:marked
+ Focus on the template:
++makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','template')(format='.')
+:marked
+ We've inserted a `` element between the `` tags.
+ Angular *projects* (*transcludes*) the corresponding `HeroContactComponent` into the `HeroBioComponent` view,
+ placing it in the `` slot of the `HeroBioComponent` template:
++makeExample('cb-dependency-injection/ts/app/hero-bio.component.ts','template','app/hero-bio.component.ts (template)')(format='.')
+:marked
+ It looks like this, with the heroe's telephone number from `HeroContactComponent` projected above the hero description:
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/hero-bio-and-content.png" alt="bio and contact")
+:marked
+ Here's the `HeroContactComponent` which demonstrates the qualifying decorators that we're talking about in this section:
++makeExample('cb-dependency-injection/ts/app/hero-contact.component.ts','component','app/hero-contact.component.ts')
+:marked
+ Focus on the constructor parameters
++makeExample('cb-dependency-injection/ts/app/hero-contact.component.ts','ctor-params','app/hero-contact.component.ts')(format='.')
+:marked
+ The `@Host()` function decorating the `_heroCache` property ensures that
+ we get a reference to the cache service from the parent `HeroBioComponent`.
+ Angular throws if the parent lacks that service, even if a component higher in the component tree happens to have that service.
+
+ A second `@Host()` function decorates the `_loggerService` property.
+ We know the only `LoggerService` instance in the app is provided at the `AppComponent` level.
+ The host `HeroBioComponent` doesn't have its own `LoggerService` provider.
+
+ Angular would throw an error if we hadn't also decorated the property with the `@Optional()` function.
+ Thanks to `@Optional()`, Angular sets the `loggerService` to null and the rest of the component adapts.
+
+.l-sub-section
+ :marked
+ We'll come back to the `elementRef` property shortly.
+:marked
+ Here's the `HeroBiosAndContactsComponent` in action.
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/hero-bios-and-contacts.png" alt="Bios with contact into")
+:marked
+ If we comment out the `@Host()` decorator, Angular now walks up the injector ancestor tree
+ until it finds the logger at the `AppComponent` level. The logger logic kicks in and the hero display updates
+ with the gratuituous "!!!", indicating that the logger was found.
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/hero-bio-contact-no-host.png" alt="Without @Host")
+:marked
+ On the other hand, if we restore the `@Host()` decorator and comment out `@Optional`,
+ the application fails for lack of the required logger at the host component level.
+
+ `EXCEPTION: No provider for LoggerService! (HeroContactComponent -> LoggerService)`
+
+
+:marked
+ ## Inject the component's element
+
+ On occasion we might need to access a component's corresponding DOM element.
+ Although we strive to avoid it, many visual effects and 3rd party tools (such as jQuery)
+ require DOM access.
+
+ To illustrate, we've written a simplified version of the `HighlightDirective` from
+ the [Attribute Directives](../guide/attribute-directives.html) chapter.
++makeExample('cb-dependency-injection/ts/app/highlight.directive.ts','','app/highlight.directive.ts')
+:marked
+ The directive sets the background to a highlight color when the user mouses over the
+ DOM element to which it is applied.
+
+ Angular set the constructor's `el` parameter to the injected `ElementRef` which is
+ a wrapper around that DOM element.
+ Its `nativeElement` property exposes the DOM element for the directive to manipulate.
+
+ The sample code applies the directive's `myHighlight` attribute to two `
` tags,
+ first without a value (yielding the default color) and then with an assigned color value.
++makeExample('cb-dependency-injection/ts/app/app.component.html','highlight','app/app.component.html (highlight)')(format='.')
+:marked
+ The following image shows the effect of mousing over the `` tag.
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/highlight.png" alt="Highlighted bios")
+:marked
+
+
+.l-main-section
+:marked
+ ## Define dependencies with providers
+
+ In this section we learn to write providers that deliver dependent services.
+
+ ### Background
+ We get a service from a dependency injector by giving it a ***token***.
+
+ We usually let Angular handle this transaction for us by specifying a constructor parameter and its type.
+ The parameter type serves as the injector lookup *token*.
+ Angular passes this token to the injector and assigns the result to the parameter.
+ Here's a typical example:
+
++makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','ctor','app/hero-bios.component.ts (component constructor injection)')(format='.')
+:marked
+ Angular asks the injector for the service associated with the `LoggerService` and
+ and assigns the returned value to the `logger` parameter.
+
+ Where did the injector get that value?
+ It may already have that value in its internal container.
+ It it doesn't, it may be able to make one with the help of a ***provider***.
+ A *provider* is a recipe for delivering a service associated with a *token*.
+.l-sub-section
+ :marked
+ If the injector doesn't have a provider for the requested *token*, it delegates the request
+ to its parent injector, where the process repeats until there are no more injectors.
+ If the search is futile, the injector throws an error ... unless the request was [optional](#optional).
+
+ Let's return our attention to providers themselves.
+:marked
+ A new injector has no providers.
+ Angular initializes the injectors it creates with some providers it cares about.
+ We have to register our _own_ application providers manually,
+ usually in the `providers` array of the `Component` or `Directive` metadata:
++makeExample('cb-dependency-injection/ts/app/app.component.ts','providers','app/app.component.ts (providers)')
+:marked
+ ### Defining providers
+
+ The simple class provider is the most typical by far.
+ We mention the class in the `providers` array and we're done.
++makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','class-provider','app/hero-bios.component.ts (class provider)')(format='.')
+:marked
+ It's that simple because the most common injected service is an instance of a class.
+ But not every dependency can be satisfied by creating a new instance of a class.
+ We need other ways to deliver dependency values and that means we need other ways to specify a provider.
+
+ The `HeroOfTheMonthComponent` example demonstrates many of the alternatives and why we need them.
+
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/hero-of-month.png" alt="Hero of the month" width="300px")
+:marked
+ It's visually simple: a few properties and the output of a logger. The code behind it gives us plenty to talk about.
++makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','hero-of-the-month','hero-of-the-month.component.ts')
+
+.l-main-section
+a(id='provide')
+:marked
+ #### The *provide* function
+
+ The imported Angular `provide` function creates an instance of
+ the Angular [Provider](../api/core/Provider-class.html) class.
+
+ The `provide` function takes a *token* and a *definition object*.
+ The *token* is usually a class but [it doesn't have to be](#tokens).
+
+ The *definition* object has one main property, (e.g. `useValue`) that indicates how the provider
+ should create or return the provided value.
+
+.l-main-section
+a(id='usevalue')
+:marked
+ #### useValue - the *value provider*
+
+ Set the `useValue` property to a ***fixed value*** that the provider can return as the dependency object.
+
+ Use this technique to provide *runtime configuration constants* such as web-site base addresses and feature flags.
+ We often use a *value provider* in a unit test to replace a production service with a fake or mock.
+
+ The `HeroOfTheMonthComponent` example has two *value providers*.
+ The first provides an instance of the `Hero` class;
+ the second specifies a literal string resource:
++makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','use-value')(format='.')
+:marked
+ The `Hero` provider token is a class which makes sense because the value is a `Hero`
+ and the consumer of the injected hero would want the type information.
+
+ The `TITLE` provider token is *not a class*.
+ It's a special kind of provider lookup key called an [OpaqueToken](#opaquetoken).
+ We often use an `OpaqueToken` when the dependency is a simple value like a string, a number, or a function.
+
+ The value of a *value provider* must be defined *now*. We can't create the value later.
+ Obviously the title string literal is immediately available.
+ The `someHero` variable in this example was set earlier in the file:
++makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','some-hero')
+:marked
+ The other providers create their values *lazily* when they're needed for injection.
+
+.l-main-section
+a(id='useclass')
+:marked
+ #### useClass - the *class provider*
+
+ The `useClass` provider creates and returns new instance of the specified class.
+
+ Use this technique to ***substitute an alternative implementation*** for a common or default class.
+ The alternative could implement a different strategy, extend the default class,
+ or fake the behavior of the real class in a test case.
+
+ We see two examples in the `HeroOfTheMonthComponent`:
++makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','use-class')(format='.')
+:marked
+ The first provider is the *de-sugared*, expanded form of the most typical case in which the
+ class to be created (`HeroService`) is also the provider's injection token.
+ We wrote it in this long form to de-mystify the preferred short form.
+
+ The second provider substitutes the `DateLoggerService` for the `LoggerService`.
+ The `LoggerService` is already registered at the `AppComponent` level.
+ When _this component_ requests the `LoggerService`, it receives the `DateLoggerService` instead.
+.l-sub-section
+ :marked
+ This component and its tree of child components receive the `DateLoggerService` instance.
+ Components outside the tree continue to receive the original `LoggerService` instance.
+:marked
+ The `DateLoggerService` inherits from `LoggerService`; it appends the current date/time to each message:
++makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','date-logger-service','app/date-logger.service.ts')(format='.')
+
+.l-main-section
+a(id='useexisting')
+:marked
+ #### useExisting - the *alias provider*
+
+ The `useExisting` provider maps one token to another.
+ In effect, the first token is an ***alias*** for the service associated with second token,
+ creating ***two ways to access the same service object***.
++makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','use-existing')
+:marked
+ Narrowing an API through an aliasing interface is _one_ important use case for this technique.
+ We're aliasing for that very purpose here.
+ Imagine that the `LoggerService` had a large API (it's actually only three methods and a property).
+ We want to shrink that API surface to just the two members exposed by the `MinimalLogger` [*class-interface*](#class-interface):
+
++makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','minimal-logger','app/date-logger.service.ts (MinimalLogger)')(format='.')
+:marked
+ The constructor's `logger` parameter is typed as `MinimalLogger` so only its two members are visible in TypeScript:
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/minimal-logger-intellisense.png" alt="MinimalLogger restricted API")
+:marked
+ Angular actually sets the `logger` parameter to the injector's full version of the `LoggerService`
+ which happens to be the `DateLoggerService` thanks to the override provider registered previously via `useClass`.
+ The following image, which displays the logging date, confirms the point:
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/date-logger-entry.png" alt="DateLoggerService entry" width="300px")
+
+.l-main-section
+a(id='usefactory')
+:marked
+ #### useFactory - the *factory provider*
+
+ The `useFactory` provider creates a dependency object by calling a factory function
+ as seen in this example.
++makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','use-factory')
+:marked
+ Use this technique to ***create a dependency object***
+ with a factory function whose inputs are some ***combination of injected services and local state***.
+
+ The *dependency object* doesn't have to be a class instance. It could be anything.
+ In this example, the *dependency object* is a string of the names of the runners-up
+ to the "Hero of the Month" contest.
+
+ The local state is the number `2`, the number of runners-up this component should show.
+ We execute `runnersUpFactory` immediately with `2`.
+
+ The `runnersUpFactory` itself isn't the provider factory function.
+ The true provider factory function is the function that `runnersUpFactory` returns.
+
++makeExample('cb-dependency-injection/ts/app/runners-up.ts','factory-synopsis','runners-up.ts (excerpt)')(format='.')
+:marked
+ That returned function takes a winning `Hero` and a `HeroService` as arguments.
+
+ Angular supplies these arguments from injected values identified by
+ the two *tokens* in the `deps` array.
+ The two `deps` values are *tokens* that the injector uses
+ to provide these factory function dependencies.
+
+ After some undisclosed work, the function returns the string of names
+ and Angular injects it into the `runnersUp` parameter of the `HeroOfTheMonthComponent`.
+
+.l-sub-section
+ :marked
+ The function retrieves candidate heroes from the `HeroService`,
+ takes `2` of them to be the runners-up, and returns their concatenated names.
+ Look at the [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)
+ for the full source code.
+
+
+a(id="tokens")
+.l-main-section
+:marked
+ ## Provider token alternatives: the *class-interface* and *OpaqueToken*
+
+ Angular dependency injection is easiest when the provider *token* is a class
+ that is also the type of the returned dependency object (what we usually call the *service*).
+
+ But the token doesn't have to be a class and even when it is a class,
+ it doesn't have to be the same type as the returned object.
+ That's the subject of our next section.
+
+
+ ### class-interface
+ In the previous *Hero of the Month* example, we used the `MinimalLogger` class
+ as the token for a provider of a `LoggerService`.
++makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','use-existing')
+:marked
+ The `MinimalLogger` is an abstract class.
++makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','minimal-logger')(format='.')
+:marked
+ We usually inherit from an abstract class.
+ But `LoggerService` doesn't inherit from `MinimalLogger`. *No class* inherits from it.
+ Instead, we use it like an interface.
+
+ Look again at the declaration for `DateLoggerService`
++makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','date-logger-service-signature')(format='.')
+:marked
+ `DateLoggerService` inherits (extends) from `LoggerService`, not `MinimalLogger`.
+ The `DateLoggerService` *implements* `MinimalLogger` as if `MinimalLogger` were an *interface*.
+
+ We call a class used in this way a ***class-interface***.
+ The key benefit of a *class-interface* is that we can get the strong-typing of an interface
+ and we can ***use it as a provider token*** in the same manner as a normal class.
+
+ A ***class-interface*** should define *only* the members that its consumers are allowed to call.
+ Such a narrowing interface helps decouple the concrete class from its consumers.
+ The `MinimalLogger` defines just two of the `LoggerClass` members.
+
+.l-sub-section
+ :marked
+ #### Why *MinimalLogger* is a class and not an interface
+ We can't use an interface as a provider token because
+ interfaces are not JavaScript objects.
+ They exist only in the TypeScript design space.
+ They disappear after the code is transpiled to JavaScript.
+
+ A provider token must be a real JavaScript object of some kind:
+ a function, an object, a string ... a class.
+
+ Using a class as an interface gives us the characteristics of an interface in a JavaScript object.
+
+ The minimize memory cost, the class should have *no implementation*.
+ The `MinimalLogger` transpiles to this unoptimized, pre-minified JavaScript:
+ +makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','minimal-logger-transpiled')(format='.')
+ :marked
+ It never grows larger no matter how many members we add *as long as they are typed but not implemented*.
+
+a(id='opaque-token')
+:marked
+ ### OpaqueToken
+
+ Dependency objects can be simple values like dates, numbers and strings or
+ shapeless objects like arrays and functions.
+
+ Such objects don't have application interfaces and therefore aren't well represented by a class.
+ They're better represented by a token that is both unique and symbolic,
+ a JavaScript object that has a friendly name but won't conflict with
+ another token that happens to have the same name.
+
+ The `OpaqueToken` has these characteristics.
+ We encountered them twice in the *Hero of the Month* example,
+ in the *title* value provider and in the *runnersUp* factory provider.
++makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','provide-opaque-token')(format='.')
+:marked
+ We created the `TITLE` token like this:
++makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','opaque-token')(format='.')
+
+
+a(id="di-inheritance")
+.l-main-section
+:marked
+ ## Inject into a derived class
+ We must take care when writing a component that inherits from another component.
+ If the base component has injected dependencies,
+ we must re-provide and re-inject them in the derived class
+ and then pass them down to the base class through the constructor.
+
+ In this contrived example, `SortedHeroesComponent` inherits from `HeroesBaseComponent`
+ to display a *sorted* list of heroes.
+
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/sorted-heroes.png" alt="Sorted Heroes")
+:marked
+ The `HeroesBaseComponent` could stand on its own.
+ It demands its own instance of the `HeroService` to get heroes
+ and displays them in the order they arrive from the database.
+
++makeExample('cb-dependency-injection/ts/app/sorted-heroes.component.ts','heroes-base','app/sorted-heroes.component.ts (HeroesBaseComponent)')
+.l-sub-section
+ :marked
+ We strongly prefer simple constructors. They should do little more than initialize variables.
+ This rule makes the component safe to construct under test without fear that it will do something dramatic like talk to the server.
+ That's why we call the `HeroService` from within the `ngOnInit` rather than the constructor.
+
+ We explain the mysterious `_afterGetHeroes` below.
+:marked
+ Users want to see the heroes in alphabetical order.
+ Rather than modify the original component, we sub-class it and create a
+ `SortedHeroesComponent` that sorts the heroes before presenting them.
+ The `SortedHeroesComponent` lets the base class fetch the heroes.
+ (we said it was contrived).
+
+ Unfortunately, Angular cannot inject the `HeroService` directly into the base class.
+ We must provide the `HeroService` again for *this* component,
+ then pass it down to the base class inside the constructor.
+
++makeExample('cb-dependency-injection/ts/app/sorted-heroes.component.ts','sorted-heroes','app/sorted-heroes.component.ts (SortedHeroesComponent)')
+:marked
+ Now take note of the `_afterGetHeroes` method.
+ Our first instinct was to create an `ngOnInit` method in `SortedHeroesComponent` and do the sorting there.
+ But Angular calls the *derived* class's `ngOnInit` *before* calling the base class's `ngOnInit`
+ so we'd be sorting the heroes array *before they arrived*. That produces a nasty error.
+
+ Overriding the base class's `_afterGetHeroes` method solves the problem
+
+ These complications argue for *avoiding component inheritance*.
+
+a(id="find-parent")
+.l-main-section
+:marked
+ ## Find a parent component by injection
+
+ Application components often need to share information.
+ We prefer the more loosely coupled techniques such as data binding and service sharing.
+ But sometimes it makes sense for one component to have a direct reference to another component
+ perhaps to access values or call methods on that component.
+
+ Obtaining a component reference is a bit tricky in Angular.
+ Although an Angular application is a tree of components,
+ there is no public API for inspecting and traversing that tree.
+
+ There is an API for acquiring a child reference
+ (checkout `Query`, `QueryList`, `ViewChildren`, and `ContentChildren`).
+
+ There is no public API for acquiring a parent reference.
+ But because every component instance is added to an injector's container,
+ we can use Angular dependency injection to reach a parent component.
+
+ This section describes some techniques for doing that.
+
+
+ ### Find a parent component of known type
+
+ We use standard class injection to acquire a parent component whose type we know.
+
+ In the following example, the parent `AlexComponent` has several children including a `CathyComponent`:
+a(id='alex')
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alex-1','parent-finder.component.ts (AlexComponent v.1)')(format='.')
+:marked
+ *Cathy* reports whether or not she has access to *Alex*
+ after injecting an `AlexComponent` into her constructor:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','cathy','parent-finder.component.ts (CathyComponent)')(format='.')
+:marked
+ We added the [@Optional](#optional) qualifier for safety but
+ the [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)
+ confirms that the `alex` parameter is set.
+
+
+ ### Cannot find a parent by its base class
+
+ What if we do *not* know the concrete parent component class?
+
+ A re-usable component might be a child of multiple components.
+ Imagine a component for rendering breaking news about a financial instrument.
+ For sound (cough) business reasons, this news component makes frequent calls
+ directly into its parent instrument as changing market data stream by.
+
+ The app probably defines more than a dozen financial instrument components.
+ If we're lucky, they all implement the same base class
+ whose API our `NewsComponent` understands.
+
+.l-sub-section
+ :marked
+ Looking for components that implement an interface would be better.
+ That's not possible because TypeScript interfaces disappear from the transpiled JavaScript
+ which doesn't support interfaces. There's no artifact we could look for.
+:marked
+ We're not claiming this is good design.
+ We are asking *can a component inject its parent via the parent's base class*?
+
+ The sample's `CraigComponent` explores this question. [Looking back](#alex)
+ we see that the `Alex` component *extends* (*inherits*) from a class named `Base`.
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alex-class-signature','parent-finder.component.ts (Alex class signature)')(format='.')
+:marked
+ The `CraigComponent` tries to inject `Base` into its `alex` constructor parameter and reports if it succeeded.
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','craig','parent-finder.component.ts (CraigComponent)')(format='.')
+:marked
+ Unfortunately, this does not work.
+ The [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)
+ confirms that the `alex` parameter is null.
+ *We cannot inject a parent by its base class.*
+
+
+ ### Find a parent by its class-interface
+
+ We can find a parent component with a [class-interface](#class-interface).
+
+ The parent must cooperate by providing an *alias* to itself in the name of a *class-interface* token.
+
+ Recall that Angular always adds a component instance to its own injector;
+ that's why we could inject *Alex* into *Carol* [earlier](#known-parent).
+
+ We write an [*alias provider*](#useexisting) — a `provide` function with a `useExisting` definition —
+ that creates an *alternative* way to inject the same component instance
+ and add that provider to the `providers` array of the `@Component` metadata for the `AlexComponent`:
+a(id="alex-providers")
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alex-providers','parent-finder.component.ts (AlexComponent providers)')(format='.')
+:marked
+ [Parent](#parent-token) is the provider's *class-interface* token.
+ The [*forwardRef*](#forwardref) breaks the circular reference we just created by having the `AlexComponent` refer to itself.
+
+ *Carol*, the third of *Alex*'s child components, injects the parent into its `parent` parameter, the same way we've done it before:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','carol-class','parent-finder.component.ts (CarolComponent class)')(format='.')
+:marked
+ Here's *Alex* and family in action:
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/alex.png" alt="Alex in action")
+
+a(id="parent-tree")
+:marked
+ ### Find the parent in a tree of parents
+
+ Imagine one branch of a component hierarchy: *Alice* -> *Barry* -> *Carol*.
+ Both *Alice* and *Barry* implement the `Parent` *class-interface*.
+
+ *Barry* is the problem. He needs to reach his parent, *Alice*, and also be a parent to *Carol*.
+ That means he must both *inject* the `Parent` *class-interface* to get *Alice* and
+ *provide* a `Parent` to satisfy *Carol*.
+
+ Here's *Barry*:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','barry','parent-finder.component.ts (BarryComponent)')(format='.')
+:marked
+ *Barry*'s `providers` array looks just like [*Alex*'s](#alex-providers).
+ If we're going to keep writing [*alias providers*](#useexisting) like this we should create a [helper function](#provideparent).
+
+ For now, focus on *Barry*'s constructor:
++makeTabs(
+ 'cb-dependency-injection/ts/app/parent-finder.component.ts, cb-dependency-injection/ts/app/parent-finder.component.ts',
+ 'barry-ctor, carol-ctor',
+ 'Barry\'s constructor, Carol\'s constructor')(format='.')
+:marked
+:marked
+ It's identical to *Carol*'s constructor except for the additional `@SkipSelf` decorator.
+
+ `@SkipSelf` is essential for two reasons:
+
+ 1. It tell the injector to start its search for a `Parent` dependency in a component *above* itself,
+ which *is* what parent means.
+
+ 2. Angular throws a cyclic dependency error if we omit the `@SkipSelf` decorator.
+
+ `Cannot instantiate cyclic dependency! (BethComponent -> Parent -> BethComponent)`
+
+ Here's *Alice*, *Barry* and family in action:
+
+figure.image-display
+ img(src="/resources/images/cookbooks/dependency-injection/alice.png" alt="Alice in action")
+
+a(id="parent-token")
+:marked
+ ### The *Parent* class-interface
+ We [learned earlier](#class-interface) that a *class-interface* is an abstract class used as an interface rather than as a base class.
+
+ Our example defines a `Parent` *class-interface* .
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','parent','parent-finder.component.ts (Parent class-interface)')(format='.')
+:marked
+ The `Parent` *class-interface* defines a `name` property with a type declaration but *no implementation*.,
+ The `name` property is the only member of a parent component that a child component can call.
+ Such a narrowing interface helps decouple the child component class from its parent components.
+
+ A component that could serve as a parent *should* implement the *class-interface* as the `AliceComponent` does:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alice-class-signature','parent-finder.component.ts (AliceComponent class signature)')(format='.')
+:marked
+ Doing so adds clarity to the code. But it's not technically necessary.
+ Although the `AlexComponent` has a `name` property (as required by its `Base` class)
+ its class signature doesn't mention `Parent`:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alex-class-signature','parent-finder.component.ts (AlexComponent class signature)')(format='.')
+.l-sub-section
+ :marked
+ The `AlexComponent` *should* implement `Parent` as a matter of proper style.
+ It doesn't in this example *only* to demonstrate that the code will compile and run without the interface
+
+a(id="provideparent")
+:marked
+ ### A *provideParent* helper function
+
+ Writing variations of the same parent *alias provider* gets old quickly,
+ especially this awful mouthful with a [*forwardRef*](#forwardref):
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alex-providers')(format='.')
+:marked
+ We can extract that logic into a helper function like this:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','provide-the-parent')(format='.')
+:marked
+ Now we can add a simpler, more meaningful parent provider to our components:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alice-providers')(format='.')
+:marked
+ We can do better. The current version of the helper function can only alias the `Parent` *class-interface*.
+ Our application might have a variety of parent types, each with its own *class-interface* token.
+
+ Here's a revised version that defaults to `parent` but also accepts an optional second parameter for a different parent *class-interface*.
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','provide-parent')(format='.')
+:marked
+ And here's how we could use it with a different parent type:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','beth-providers')(format='.')
+:marked
+
+a(id="forwardref")
+.l-main-section
+:marked
+ ## Break circularities with a forward class reference (*forwardRef*)
+
+ The order of class declaration matters in TypeScript.
+ We can't refer directly to a class until it's been defined.
+
+ This isn't usually a problem, especially if we adhere to the recommended *one class per file* rule.
+ But sometimes circular references are unavoidable.
+ We're in a bind when class 'A refers to class 'B' and 'B' refers to 'A'.
+ One of them has to be defined first.
+
+ The Angular `forwardRef` function creates an *indirect* reference that Angular can resolve later.
+
+ The *Parent Finder* sample is full of circular class references that are impossible to break.
+
+ In the [*Alex/Cathy* example](#known-parent) above:
+
+ * the `AlexComponent` lists the `CathyComponent` in its component metadata `directives` array
+ so it can display *Cathy* in its template.
+
+ * the `CathyComponent` constructor injects the parent `AlexComponent` which means that the `alex` parameter
+ of its constructor has the `AlexComponent` type.
+
+ *Alex* refers to *Cathy* and *Cathy* refers to *Alex*. We're stuck. We must define one of them first.
+
+ We defined *Alex* first and built its `C_DIRECTIVES` array with a forward reference to *Cathy*:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','C_DIRECTIVES','parent-finder.component.ts (C_DIRECTIVES)')(format='.')
+:marked
+.l-sub-section
+ :marked
+ Defining *Alex* and *Cathy* in separate files won't help.
+ *Alex* would have to import *Cathy* and *Cathy* would have to import *Alex*.
+
+ We *had* to define *Alex* first because,
+ while we can add `forwardRef(CathyComponent)` to *Alex*'s `directives` array,
+ we can't write `public alex: forwardRef(AlexComponent))` in *Cathy*'s constructor.
+:marked
+ We face a similar dilemma when a class makes *a reference to itself*
+ as does the `AlexComponent` in its `providers` array.
+ The `providers` array is a property of the `@Component` decorator function which must
+ appear *above* the class definition.
+
+ Again we break the circularity with `forwardRef`:
++makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alex-providers','parent-finder.component.ts (AlexComponent providers)')(format='.')
+:marked
diff --git a/public/docs/ts/latest/guide/attribute-directives.jade b/public/docs/ts/latest/guide/attribute-directives.jade
index b9bc22fcf9..7452ac19c8 100644
--- a/public/docs/ts/latest/guide/attribute-directives.jade
+++ b/public/docs/ts/latest/guide/attribute-directives.jade
@@ -186,12 +186,9 @@ figure.image-display
Now we implement those two mouse event handlers:
+makeExample('attribute-directives/ts/app/highlight.directive.2.ts','mouse-methods')(format=".")
:marked
- Notice that they delegate to a helper method to set the color.
-
- We no longer need the constructor body but
- we still want the injected `ElementRef`.
- We revise the constructor signature to capture the injected `ElementRef` in a private variable
- and clear the body.
+ Notice that they delegate to a helper method that sets the color via a private local variable, `_el`.
+ We revise the constructor to capture the `ElementRef.nativeElement` in `_el`.
+
+makeExample('attribute-directives/ts/app/highlight.directive.2.ts','ctor')(format=".")
:marked
Here's the updated directive:
diff --git a/public/docs/ts/latest/guide/dependency-injection.jade b/public/docs/ts/latest/guide/dependency-injection.jade
index d34df913d2..72b7ed695c 100644
--- a/public/docs/ts/latest/guide/dependency-injection.jade
+++ b/public/docs/ts/latest/guide/dependency-injection.jade
@@ -411,13 +411,18 @@ include ../_util-fns
- var decorated = lang == 'dart' ? 'annotated' : 'decorated'
- var any_decorator = lang == 'dart' ? '' : 'TypeScript generates metadata for any class with a decorator, and any decorator will do.'
.callout.is-helpful
- header Always add @Injectable()
+ header Suggestion: add @Injectable() to every service class
:marked
We recommend adding `@Injectable()` to every service class, even those that don't have dependencies
and, therefore, do not technically require it. Here's why:
ul(style="font-size:inherit")
li Future proofing: No need to remember @Injectable() when we add a dependency later.
li Consistency: All services follow the same rules, and we don't have to wonder why #{a_decorator} is missing.
+
+ :marked
+ Although we recommend applying `@Injectable` to all service classes, do not feel bound by it.
+ Some developers prefer to add it only where needed and that's a reasonable policy too.
+
.l-sub-section
:marked
The `HeroesComponent` has an injected dependency too. Why don't we add `@Injectable()` to the `HeroesComponent`?
diff --git a/public/docs/ts/latest/guide/pipes.jade b/public/docs/ts/latest/guide/pipes.jade
index 54b0401aa9..42abb48a7e 100644
--- a/public/docs/ts/latest/guide/pipes.jade
+++ b/public/docs/ts/latest/guide/pipes.jade
@@ -312,8 +312,7 @@ figure.image-display
+makeExample('pipes/ts/app/flying-heroes.pipe.ts','filter')(format='.')
We can derive a `FlyingHeroesImpureComponent` that we derive from the `FlyingHeroesComponent`.
-+makeExample('pipes/ts/app/flying-heroes.component.ts','impure-component',
-'app/flying-heroes.component.ts (FlyingHeroesImpureComponent)')(format='.')
++makeExample('pipes/ts/app/flying-heroes.component.ts','impure-component','app/flying-heroes.component.ts (FlyingHeroesImpureComponent)')(format='.')
:marked
The only substantive change is the pipe.
We can confirm in the [live example](/resources/live-examples/pipes/ts/plnkr.html)
diff --git a/public/docs/ts/latest/guide/router.jade b/public/docs/ts/latest/guide/router.jade
index cec2c638bb..594d2d467a 100644
--- a/public/docs/ts/latest/guide/router.jade
+++ b/public/docs/ts/latest/guide/router.jade
@@ -1386,9 +1386,10 @@ code-example(format="." language="bash").
`HeroService` and (perhaps) mocking it.
+
.l-main-section
:marked
- ## Appendix: Browser URL styles
+ ## Appendix: *LocationStrategy* and browser URL styles
When the router navigates to a new component view, it updates the browser's location and history
with a URL for that view.
diff --git a/public/resources/images/cookbooks/dependency-injection/alex.png b/public/resources/images/cookbooks/dependency-injection/alex.png
new file mode 100644
index 0000000000..06a9762024
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/alex.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/alice.png b/public/resources/images/cookbooks/dependency-injection/alice.png
new file mode 100644
index 0000000000..48d311b37f
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/alice.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/date-logger-entry.png b/public/resources/images/cookbooks/dependency-injection/date-logger-entry.png
new file mode 100644
index 0000000000..fe7c9953c3
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/date-logger-entry.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/hero-bio-and-content.png b/public/resources/images/cookbooks/dependency-injection/hero-bio-and-content.png
new file mode 100644
index 0000000000..bc6ee5da9a
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/hero-bio-and-content.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/hero-bio-contact-no-host.png b/public/resources/images/cookbooks/dependency-injection/hero-bio-contact-no-host.png
new file mode 100644
index 0000000000..62211bbae6
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/hero-bio-contact-no-host.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/hero-bios-and-contacts.png b/public/resources/images/cookbooks/dependency-injection/hero-bios-and-contacts.png
new file mode 100644
index 0000000000..9b196cbd0b
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/hero-bios-and-contacts.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/hero-bios.png b/public/resources/images/cookbooks/dependency-injection/hero-bios.png
new file mode 100644
index 0000000000..df3fd2140d
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/hero-bios.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/hero-of-month.png b/public/resources/images/cookbooks/dependency-injection/hero-of-month.png
new file mode 100644
index 0000000000..f7d485df3e
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/hero-of-month.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/highlight.png b/public/resources/images/cookbooks/dependency-injection/highlight.png
new file mode 100644
index 0000000000..e3dced717c
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/highlight.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/logged-in-user.png b/public/resources/images/cookbooks/dependency-injection/logged-in-user.png
new file mode 100644
index 0000000000..4a43da33c9
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/logged-in-user.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/minimal-logger-intellisense.png b/public/resources/images/cookbooks/dependency-injection/minimal-logger-intellisense.png
new file mode 100644
index 0000000000..1f02db8d76
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/minimal-logger-intellisense.png differ
diff --git a/public/resources/images/cookbooks/dependency-injection/sorted-heroes.png b/public/resources/images/cookbooks/dependency-injection/sorted-heroes.png
new file mode 100644
index 0000000000..6adfeae498
Binary files /dev/null and b/public/resources/images/cookbooks/dependency-injection/sorted-heroes.png differ
diff --git a/tools/plunker-builder/plunkerBuilder.js b/tools/plunker-builder/plunkerBuilder.js
index cb1c405de9..bf784f1e32 100644
--- a/tools/plunker-builder/plunkerBuilder.js
+++ b/tools/plunker-builder/plunkerBuilder.js
@@ -107,14 +107,16 @@ function initConfigAndCollectFileNames(configFileName) {
}
});
// var defaultExcludes = [ '!**/node_modules/**','!**/typings/**','!**/tsconfig.json', '!**/*plnkr.json', '!**/*plnkr.html', '!**/*plnkr.no-link.html' ];
- var defaultExcludes = [
+ var defaultExcludes = [
'!**/typings/**',
'!**/typings.json',
- '!**/tsconfig.json',
- '!**/*plnkr.*',
- '!**/package.json',
+ '!**/tsconfig.json',
+ '!**/*plnkr.*',
+ '!**/package.json',
'!**/example-config.json',
- '!**/*.spec.*'
+ '!**/*.spec.*',
+ '!**/tslint.json',
+ '!**/.editorconfig'
];
Array.prototype.push.apply(gpaths, defaultExcludes);
@@ -263,4 +265,4 @@ function escapeHtml(unsafe) {
// fs.writeFileSync(outputFn, html, 'utf-8' );
// }
// });
-//}
\ No newline at end of file
+//}