docs(di): update docs on di
This commit is contained in:
31
modules/@angular/examples/core/di/ts/injector_spec.ts
Normal file
31
modules/@angular/examples/core/di/ts/injector_spec.ts
Normal 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
|
||||
|
||||
});
|
||||
});
|
||||
}
|
176
modules/@angular/examples/core/di/ts/metadata_spec.ts
Normal file
176
modules/@angular/examples/core/di/ts/metadata_spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
149
modules/@angular/examples/core/di/ts/provider_spec.ts
Normal file
149
modules/@angular/examples/core/di/ts/provider_spec.ts
Normal 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
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user