docs(di): update docs on di

This commit is contained in:
Tobias Bosch
2016-09-14 09:43:01 -07:00
parent d299ce4bcf
commit 0a2132ef10
7 changed files with 526 additions and 377 deletions

View File

@ -0,0 +1,31 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Injector, ReflectiveInjector} from '@angular/core';
export function main() {
describe('injector metadata examples', () => {
it('works', () => {
// #docregion Injector
const injector: Injector =
ReflectiveInjector.resolveAndCreate([{provide: 'validToken', useValue: 'Value'}]);
expect(injector.get('validToken')).toEqual('Value');
expect(() => injector.get('invalidToken')).toThrowError();
expect(injector.get('invalidToken', 'notFound')).toEqual('notFound');
// #enddocregion
});
it('injects injector', () => {
// #docregion injectInjector
const injector = ReflectiveInjector.resolveAndCreate([]);
expect(injector.get(Injector)).toBe(injector);
// #enddocregion
});
});
}

View File

@ -0,0 +1,176 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component, Directive, Host, Inject, Injectable, Optional, ReflectiveInjector, Self, SkipSelf} from '@angular/core';
import {TestBed} from '@angular/core/testing';
export function main() {
describe('di metadata examples', () => {
describe('Inject', () => {
it('works', () => {
// #docregion Inject
class Engine {}
@Injectable()
class Car {
constructor(@Inject('MyEngine') public engine: Engine) {}
}
const injector =
ReflectiveInjector.resolveAndCreate([{provide: 'MyEngine', useClass: Engine}, Car]);
expect(injector.get(Car).engine instanceof Engine).toBe(true);
// #enddocregion
});
it('works without decorator', () => {
// #docregion InjectWithoutDecorator
class Engine {}
@Injectable()
class Car {
constructor(public engine: Engine) {
} // same as constructor(@Inject(Engine) engine:Engine)
}
const injector = ReflectiveInjector.resolveAndCreate([Engine, Car]);
expect(injector.get(Car).engine instanceof Engine).toBe(true);
// #enddocregion
});
});
describe('Optional', () => {
it('works', () => {
// #docregion Optional
class Engine {}
@Injectable()
class Car {
constructor(@Optional() public engine: Engine) {}
}
const injector = ReflectiveInjector.resolveAndCreate([Car]);
expect(injector.get(Car).engine).toBeNull();
// #enddocregion
});
});
describe('Injectable', () => {
it('works', () => {
// #docregion Injectable
@Injectable()
class UsefulService {
}
@Injectable()
class NeedsService {
constructor(public service: UsefulService) {}
}
const injector = ReflectiveInjector.resolveAndCreate([NeedsService, UsefulService]);
expect(injector.get(NeedsService).service instanceof UsefulService).toBe(true);
// #enddocregion
});
it('throws without Injectable', () => {
// #docregion InjectableThrows
class UsefulService {}
class NeedsService {
constructor(public service: UsefulService) {}
}
expect(() => ReflectiveInjector.resolveAndCreate([NeedsService, UsefulService])).toThrow();
// #enddocregion
});
});
describe('Self', () => {
it('works', () => {
// #docregion Self
class Dependency {}
@Injectable()
class NeedsDependency {
constructor(@Self() public dependency: Dependency) {}
}
let inj = ReflectiveInjector.resolveAndCreate([Dependency, NeedsDependency]);
const nd = inj.get(NeedsDependency);
expect(nd.dependency instanceof Dependency).toBe(true);
inj = ReflectiveInjector.resolveAndCreate([Dependency]);
const child = inj.resolveAndCreateChild([NeedsDependency]);
expect(() => child.get(NeedsDependency)).toThrowError();
// #enddocregion
});
});
describe('SkipSelf', () => {
it('works', () => {
// #docregion SkipSelf
class Dependency {}
@Injectable()
class NeedsDependency {
constructor(@SkipSelf() public dependency: Dependency) { this.dependency = dependency; }
}
const parent = ReflectiveInjector.resolveAndCreate([Dependency]);
const child = parent.resolveAndCreateChild([NeedsDependency]);
expect(child.get(NeedsDependency).dependency instanceof Dependency).toBe(true);
const inj = ReflectiveInjector.resolveAndCreate([Dependency, NeedsDependency]);
expect(() => inj.get(NeedsDependency)).toThrowError();
// #enddocregion
});
});
describe('Host', () => {
it('works', () => {
// #docregion Host
class OtherService {}
class HostService {}
@Directive({selector: 'child-directive'})
class ChildDirective {
constructor(@Optional() @Host() os: OtherService, @Optional() @Host() hs: HostService) {
console.log('os is null', os);
console.log('hs is NOT null', hs);
}
}
@Component({
selector: 'parent-cmp',
providers: [HostService],
template: `
Dir: <child-directive></child-directive>
`
})
class ParentCmp {
}
@Component({
selector: 'app',
providers: [OtherService],
template: `Parent: <parent-cmp></parent-cmp>`
})
class App {
}
// #enddocregion
TestBed.configureTestingModule({
declarations: [App, ParentCmp, ChildDirective],
});
expect(() => TestBed.createComponent(App)).not.toThrow();
});
});
});
}

View File

@ -0,0 +1,149 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, OpaqueToken, Optional, ReflectiveInjector, ValueProvider} from '@angular/core';
export function main() {
describe('Provider examples', () => {
describe('TypeProvider', () => {
it('works', () => {
// #docregion TypeProvider
@Injectable()
class Greeting {
salutation = 'Hello';
}
const injector = ReflectiveInjector.resolveAndCreate([
Greeting, // Shorthand for { provide: Greeting, useClass: Greeting }
]);
expect(injector.get(Greeting).salutation).toBe('Hello');
// #enddocregion
});
});
describe('ValueProvider', () => {
it('works', () => {
// #docregion ValueProvider
const injector =
ReflectiveInjector.resolveAndCreate([{provide: String, useValue: 'Hello'}]);
expect(injector.get(String)).toEqual('Hello');
// #enddocregion
});
});
describe('MultiProviderAspect', () => {
it('works', () => {
// #docregion MultiProviderAspect
const injector = ReflectiveInjector.resolveAndCreate([
{provide: 'local', multi: true, useValue: 'en'},
{provide: 'local', multi: true, useValue: 'sk'},
]);
const locales: string[] = injector.get('local');
expect(locales).toEqual(['en', 'sk']);
// #enddocregion
});
});
describe('ClassProvider', () => {
it('works', () => {
// #docregion ClassProvider
abstract class Shape { name: string; }
class Square extends Shape {
name = 'square';
}
const injector = ReflectiveInjector.resolveAndCreate([{provide: Shape, useClass: Square}]);
const shape: Shape = injector.get(Shape);
expect(shape.name).toEqual('square');
expect(shape instanceof Square).toBe(true);
// #enddocregion
});
it('is different then useExisting', () => {
// #docregion ClassProviderDifference
class Greeting {
salutation = 'Hello';
}
class FormalGreeting extends Greeting {
salutation = 'Greetings';
}
const injector = ReflectiveInjector.resolveAndCreate(
[FormalGreeting, {provide: Greeting, useClass: FormalGreeting}]);
// The injector returns different instances.
// See: {provide: ?, useExisting: ?} if you want the same instance.
expect(injector.get(FormalGreeting)).not.toBe(injector.get(Greeting));
// #enddocregion
});
});
describe('ExistingProvider', () => {
it('works', () => {
// #docregion ExistingProvider
class Greeting {
salutation = 'Hello';
}
class FormalGreeting extends Greeting {
salutation = 'Greetings';
}
const injector = ReflectiveInjector.resolveAndCreate(
[FormalGreeting, {provide: Greeting, useExisting: FormalGreeting}]);
expect(injector.get(Greeting).salutation).toEqual('Greetings');
expect(injector.get(FormalGreeting).salutation).toEqual('Greetings');
expect(injector.get(FormalGreeting)).toBe(injector.get(Greeting));
// #enddocregion
});
});
describe('FactoryProvider', () => {
it('works', () => {
// #docregion FactoryProvider
const Location = new OpaqueToken('location');
const Hash = new OpaqueToken('hash');
const injector = ReflectiveInjector.resolveAndCreate([
{provide: Location, useValue: 'http://angular.io/#someLocation'}, {
provide: Hash,
useFactory: (location: string) => location.split('#')[1],
deps: [Location]
}
]);
expect(injector.get(Hash)).toEqual('someLocation');
// #enddocregion
});
it('supports optional dependencies', () => {
// #docregion FactoryProviderOptionalDeps
const Location = new OpaqueToken('location');
const Hash = new OpaqueToken('hash');
const injector = ReflectiveInjector.resolveAndCreate([{
provide: Hash,
useFactory: (location: string) => `Hash for: ${location}`,
// use a nested array to define metadata for dependencies.
deps: [[new Optional(), new Inject(Location)]]
}]);
expect(injector.get(Hash)).toEqual('Hash for: null');
// #enddocregion
});
});
});
}