diff --git a/aio/content/examples/dependency-injection/e2e/app.e2e-spec.ts b/aio/content/examples/dependency-injection/e2e/app.e2e-spec.ts
index b61acf3a1e..472f1411fd 100644
--- a/aio/content/examples/dependency-injection/e2e/app.e2e-spec.ts
+++ b/aio/content/examples/dependency-injection/e2e/app.e2e-spec.ts
@@ -178,6 +178,11 @@ describe('Dependency Injection Tests', function () {
expect(heroes.count()).toBeGreaterThan(0);
});
+ it('authorized user should have multiple authorized heroes with tree-shakeable HeroesService', function () {
+ let heroes = element.all(by.css('#tspAuthorized app-hero-list div'));
+ expect(heroes.count()).toBeGreaterThan(0);
+ });
+
it('authorized user should have secret heroes', function () {
let heroes = element.all(by.css('#authorized app-hero-list div'));
expect(heroes.count()).toBeGreaterThan(0);
diff --git a/aio/content/examples/dependency-injection/src/app/app.component.ts b/aio/content/examples/dependency-injection/src/app/app.component.ts
index f9b4dc9842..b69856fa0a 100644
--- a/aio/content/examples/dependency-injection/src/app/app.component.ts
+++ b/aio/content/examples/dependency-injection/src/app/app.component.ts
@@ -21,6 +21,7 @@ import { UserService } from './user.service';
+
`
})
diff --git a/aio/content/examples/dependency-injection/src/app/app.module.ts b/aio/content/examples/dependency-injection/src/app/app.module.ts
index 0b5f81b9fe..85becdb3b9 100644
--- a/aio/content/examples/dependency-injection/src/app/app.module.ts
+++ b/aio/content/examples/dependency-injection/src/app/app.module.ts
@@ -6,6 +6,7 @@ import { APP_CONFIG, HERO_DI_CONFIG } from './app.config';
import { AppComponent } from './app.component';
import { CarComponent } from './car/car.component';
import { HeroesComponent } from './heroes/heroes.component';
+import { HeroesTspComponent } from './heroes/heroes-tsp.component';
import { HeroListComponent } from './heroes/hero-list.component';
import { InjectorComponent } from './injector.component';
import { Logger } from './logger.service';
@@ -25,6 +26,7 @@ import { ProvidersModule } from './providers.module';
CarComponent,
HeroesComponent,
// #enddocregion ngmodule
+ HeroesTspComponent,
HeroListComponent,
InjectorComponent,
TestComponent
diff --git a/aio/content/examples/dependency-injection/src/app/heroes/hero.module.ts b/aio/content/examples/dependency-injection/src/app/heroes/hero.module.ts
new file mode 100644
index 0000000000..7f422d5d79
--- /dev/null
+++ b/aio/content/examples/dependency-injection/src/app/heroes/hero.module.ts
@@ -0,0 +1,6 @@
+// #docregion
+import { NgModule } from '@angular/core';
+
+@NgModule({})
+export class HeroModule {
+}
diff --git a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.0.ts b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.0.ts
index d496f9608c..c8136b7db5 100644
--- a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.0.ts
+++ b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.0.ts
@@ -1,6 +1,8 @@
import { Injectable } from '@angular/core';
-@Injectable()
+@Injectable({
+ providedIn: 'root',
+})
export class HeroService {
constructor() { }
}
diff --git a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.1.ts b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.1.ts
index 75b12d7c44..908d75ee65 100644
--- a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.1.ts
+++ b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.1.ts
@@ -2,7 +2,9 @@
import { Injectable } from '@angular/core';
import { HEROES } from './mock-heroes';
-@Injectable()
+@Injectable({
+ providedIn: 'root',
+})
export class HeroService {
getHeroes() { return HEROES; }
}
diff --git a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.2.ts b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.2.ts
index 0069b598db..a4c1adcd1b 100644
--- a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.2.ts
+++ b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.2.ts
@@ -3,7 +3,9 @@ import { Injectable } from '@angular/core';
import { HEROES } from './mock-heroes';
import { Logger } from '../logger.service';
-@Injectable()
+@Injectable({
+ providedIn: 'root',
+})
export class HeroService {
// #docregion ctor
diff --git a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.3.ts b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.3.ts
new file mode 100644
index 0000000000..2d43704de0
--- /dev/null
+++ b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.3.ts
@@ -0,0 +1,13 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { HEROES } from './mock-heroes';
+
+@Injectable({
+ // we declare that this service should be created
+ // by the root application injector.
+
+ providedIn: 'root',
+})
+export class HeroService {
+ getHeroes() { return HEROES; }
+}
diff --git a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.4.ts b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.4.ts
new file mode 100644
index 0000000000..0b77c78545
--- /dev/null
+++ b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.4.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { Injectable } from '@angular/core';
+import { HeroModule } from './hero.module';
+import { HEROES } from './mock-heroes';
+
+@Injectable({
+ // we declare that this service should be created
+ // by any injector that includes HeroModule.
+
+ providedIn: HeroModule,
+})
+export class HeroService {
+ getHeroes() { return HEROES; }
+}
diff --git a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.ts b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.ts
index 02c8e4a85c..6c6fc27037 100644
--- a/aio/content/examples/dependency-injection/src/app/heroes/hero.service.ts
+++ b/aio/content/examples/dependency-injection/src/app/heroes/hero.service.ts
@@ -2,8 +2,14 @@
import { Injectable } from '@angular/core';
import { HEROES } from './mock-heroes';
import { Logger } from '../logger.service';
+import { UserService } from '../user.service';
-@Injectable()
+@Injectable({
+ providedIn: 'root',
+ useFactory: (logger: Logger, userService: UserService) =>
+ new HeroService(logger, userService.user.isAuthorized),
+ deps: [Logger, UserService],
+})
export class HeroService {
// #docregion internals
constructor(
diff --git a/aio/content/examples/dependency-injection/src/app/heroes/heroes-tsp.component.ts b/aio/content/examples/dependency-injection/src/app/heroes/heroes-tsp.component.ts
new file mode 100644
index 0000000000..4d6c01b231
--- /dev/null
+++ b/aio/content/examples/dependency-injection/src/app/heroes/heroes-tsp.component.ts
@@ -0,0 +1,16 @@
+import { Component } from '@angular/core';
+
+/**
+ * A version of `HeroesComponent` that does not provide the `HeroService` (and thus relies on its
+ * `Injectable`-declared provider) in order to function.
+ *
+ * TSP stands for Tree-Shakeable Provider.
+ */
+@Component({
+ selector: 'app-heroes-tsp',
+ template: `
+
Heroes
+
+ `
+})
+export class HeroesTspComponent { }
diff --git a/aio/content/examples/dependency-injection/src/app/tree-shaking/app.module.ts b/aio/content/examples/dependency-injection/src/app/tree-shaking/app.module.ts
new file mode 100644
index 0000000000..31d79ffc23
--- /dev/null
+++ b/aio/content/examples/dependency-injection/src/app/tree-shaking/app.module.ts
@@ -0,0 +1,15 @@
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { RouterModule } from '@angular/router';
+import { ServiceModule } from './service-and-module';
+
+// #docregion
+@NgModule({
+ imports: [
+ BrowserModule,
+ RouterModule.forRoot([]),
+ ServiceModule,
+ ],
+})
+export class AppModule {
+}
diff --git a/aio/content/examples/dependency-injection/src/app/tree-shaking/service-and-module.ts b/aio/content/examples/dependency-injection/src/app/tree-shaking/service-and-module.ts
new file mode 100644
index 0000000000..11100e3ffe
--- /dev/null
+++ b/aio/content/examples/dependency-injection/src/app/tree-shaking/service-and-module.ts
@@ -0,0 +1,14 @@
+// #docregion
+import { Injectable, NgModule } from '@angular/core';
+
+@Injectable()
+export class Service {
+ doSomething(): void {
+ }
+}
+
+@NgModule({
+ providers: [Service],
+})
+export class ServiceModule {
+}
diff --git a/aio/content/examples/dependency-injection/src/app/tree-shaking/service.0.ts b/aio/content/examples/dependency-injection/src/app/tree-shaking/service.0.ts
new file mode 100644
index 0000000000..50607d7375
--- /dev/null
+++ b/aio/content/examples/dependency-injection/src/app/tree-shaking/service.0.ts
@@ -0,0 +1,11 @@
+import { Injectable } from '@angular/core';
+
+// #docregion
+@Injectable({
+ providedIn: 'root',
+ useFactory: () => new Service('dependency'),
+})
+export class Service {
+ constructor(private dep: string) {
+ }
+}
diff --git a/aio/content/examples/dependency-injection/src/app/tree-shaking/service.ts b/aio/content/examples/dependency-injection/src/app/tree-shaking/service.ts
new file mode 100644
index 0000000000..2013120432
--- /dev/null
+++ b/aio/content/examples/dependency-injection/src/app/tree-shaking/service.ts
@@ -0,0 +1,8 @@
+import { Injectable } from '@angular/core';
+
+// #docregion
+@Injectable({
+ providedIn: 'root',
+})
+export class Service {
+}
diff --git a/aio/content/examples/dependency-injection/stackblitz.json b/aio/content/examples/dependency-injection/stackblitz.json
index d487673f5e..131d2a671c 100644
--- a/aio/content/examples/dependency-injection/stackblitz.json
+++ b/aio/content/examples/dependency-injection/stackblitz.json
@@ -3,7 +3,7 @@
"files":[
"!**/*.d.ts",
"!**/*.js",
- "!**/*.[0,1,2].*",
+ "!**/*.[0,1,2,3,4].*",
"!**/dummy.module.ts"
],
"tags": ["dependency", "di"]
diff --git a/aio/content/examples/providers/src/app/app.module.ts b/aio/content/examples/providers/src/app/app.module.ts
index 9ec63c01cd..7152c203c8 100644
--- a/aio/content/examples/providers/src/app/app.module.ts
+++ b/aio/content/examples/providers/src/app/app.module.ts
@@ -6,7 +6,6 @@ import { UserService } from './user.service';
@NgModule({
imports: [ BrowserModule ],
- providers: [ UserService ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
diff --git a/aio/content/examples/providers/src/app/user.module.ts b/aio/content/examples/providers/src/app/user.module.ts
new file mode 100644
index 0000000000..0b3b67514b
--- /dev/null
+++ b/aio/content/examples/providers/src/app/user.module.ts
@@ -0,0 +1,9 @@
+import { NgModule } from '@angular/core';
+
+import { UserService } from './user.service';
+
+@NgModule({
+ providers: [UserService],
+})
+export class UserModule {
+}
diff --git a/aio/content/examples/providers/src/app/user.service.0.ts b/aio/content/examples/providers/src/app/user.service.0.ts
new file mode 100644
index 0000000000..8988a99309
--- /dev/null
+++ b/aio/content/examples/providers/src/app/user.service.0.ts
@@ -0,0 +1,7 @@
+import { Injectable } from '@angular/core';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class UserService {
+}
diff --git a/aio/content/examples/providers/src/app/user.service.1.ts b/aio/content/examples/providers/src/app/user.service.1.ts
new file mode 100644
index 0000000000..64ee94b72d
--- /dev/null
+++ b/aio/content/examples/providers/src/app/user.service.1.ts
@@ -0,0 +1,8 @@
+import { Injectable } from '@angular/core';
+import { UserModule } from './user.module';
+
+@Injectable({
+ providedIn: UserModule,
+})
+export class UserService {
+}
diff --git a/aio/content/examples/providers/src/app/user.service.spec.ts b/aio/content/examples/providers/src/app/user.service.spec.ts
index 02fbc8d952..dcf5565717 100644
--- a/aio/content/examples/providers/src/app/user.service.spec.ts
+++ b/aio/content/examples/providers/src/app/user.service.spec.ts
@@ -3,9 +3,7 @@ import { UserService } from './user.service';
describe('UserService', () => {
beforeEach(() => {
- TestBed.configureTestingModule({
- providers: [UserService]
- });
+ TestBed.configureTestingModule({});
});
it('should ...', inject([UserService], (service: UserService) => {
diff --git a/aio/content/examples/providers/src/app/user.service.ts b/aio/content/examples/providers/src/app/user.service.ts
index 2cb7a87759..096d1c8fb1 100644
--- a/aio/content/examples/providers/src/app/user.service.ts
+++ b/aio/content/examples/providers/src/app/user.service.ts
@@ -5,7 +5,9 @@ export class User {
name: string;
}
-@Injectable()
+@Injectable({
+ providedIn: 'root',
+})
export class UserService {
constructor() { }
diff --git a/aio/content/examples/providers/stackblitz.json b/aio/content/examples/providers/stackblitz.json
index 68593b9051..9f21337a05 100644
--- a/aio/content/examples/providers/stackblitz.json
+++ b/aio/content/examples/providers/stackblitz.json
@@ -3,7 +3,7 @@
"files": [
"!**/*.d.ts",
"!**/*.js",
- "!**/*.[1,2].*"
+ "!**/*.[0,1,2].*"
],
"file": "src/app/app.component.ts",
"tags": ["providers"]
diff --git a/aio/content/examples/styleguide/src/07-03/app/app.component.ts b/aio/content/examples/styleguide/src/07-03/app/app.component.ts
index f4d25e1ab6..224ab34619 100644
--- a/aio/content/examples/styleguide/src/07-03/app/app.component.ts
+++ b/aio/content/examples/styleguide/src/07-03/app/app.component.ts
@@ -8,6 +8,5 @@ import { HeroService } from './heroes';
template: `
`,
- providers: [HeroService]
})
export class AppComponent {}
diff --git a/aio/content/examples/styleguide/src/07-03/app/heroes/shared/hero.service.ts b/aio/content/examples/styleguide/src/07-03/app/heroes/shared/hero.service.ts
index 4e2f993250..d3d8857caa 100644
--- a/aio/content/examples/styleguide/src/07-03/app/heroes/shared/hero.service.ts
+++ b/aio/content/examples/styleguide/src/07-03/app/heroes/shared/hero.service.ts
@@ -5,7 +5,9 @@ import { Observable, of } from 'rxjs';
import { Hero } from './hero.model';
-@Injectable()
+@Injectable({
+ providedIn: 'root',
+})
export class HeroService {
getHeroes() {
let heroes: Hero[] = [];