cleanup(DI): clean up visibility decorators
BREAKING CHANGE: Replace @Ancestor() with @Host() @SkipSelf() Replace @Unbounded() wwith @SkipSelf() Replace @Ancestor({self:true}) with @Host() Replace @Unbounded({self:true}) with nothing Replace new AncestorMetadata() with [new HostMetadata(), new SkipSelfMetadata()] Replace new UnboundedMetadata() with new SkipSelfMetadata() Replace new Ancestor({self:true}) with new HostMetadata()
This commit is contained in:
parent
a9ec6b9064
commit
985627bd65
|
@ -5,7 +5,7 @@
|
||||||
* Annotations provide the additional information that Angular requires in order to run your
|
* Annotations provide the additional information that Angular requires in order to run your
|
||||||
* application. This module
|
* application. This module
|
||||||
* contains {@link Component}, {@link Directive}, and {@link View} annotations, as well as
|
* contains {@link Component}, {@link Directive}, and {@link View} annotations, as well as
|
||||||
* the {@link Ancestor} annotation that is used by Angular to resolve dependencies.
|
* the {@link Host} annotation that is used by Angular to resolve dependencies.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,10 @@ export {
|
||||||
InjectMetadata,
|
InjectMetadata,
|
||||||
OptionalMetadata,
|
OptionalMetadata,
|
||||||
InjectableMetadata,
|
InjectableMetadata,
|
||||||
VisibilityMetadata,
|
|
||||||
SelfMetadata,
|
SelfMetadata,
|
||||||
AncestorMetadata,
|
HostMetadata,
|
||||||
UnboundedMetadata,
|
SkipSelfMetadata,
|
||||||
DependencyMetadata,
|
DependencyMetadata
|
||||||
DEFAULT_VISIBILITY
|
|
||||||
} from './src/di/metadata';
|
} from './src/di/metadata';
|
||||||
|
|
||||||
// we have to reexport * because Dart and TS export two different sets of types
|
// we have to reexport * because Dart and TS export two different sets of types
|
||||||
|
|
|
@ -261,7 +261,7 @@ Injecting other directives into directives follows a similar mechanism as inject
|
||||||
There are five kinds of visibilities:
|
There are five kinds of visibilities:
|
||||||
|
|
||||||
* (no annotation): Inject dependent directives only if they are on the current element.
|
* (no annotation): Inject dependent directives only if they are on the current element.
|
||||||
* `@ancestor`: Inject a directive if it is at any element above the current element.
|
* `@SkipSelf()`: Inject a directive if it is at any element above the current element.
|
||||||
* `@child`: Inject a list of direct children which match a given type. (Used with `Query`)
|
* `@child`: Inject a list of direct children which match a given type. (Used with `Query`)
|
||||||
* `@descendant`: Inject a list of any children which match a given type. (Used with `Query`)
|
* `@descendant`: Inject a list of any children which match a given type. (Used with `Query`)
|
||||||
|
|
||||||
|
@ -299,8 +299,8 @@ class FieldSet { |
|
||||||
@Directive({ selector: 'field' }) |
|
@Directive({ selector: 'field' }) |
|
||||||
class Field { |
|
class Field { |
|
||||||
constructor( |
|
constructor( |
|
||||||
@ancestor field:Form, |
|
@SkipSelf() field:Form, |
|
||||||
@ancestor field:FieldSet, |
|
@SkipSelf() field:FieldSet, |
|
||||||
) { ... } |
|
) { ... } |
|
||||||
} |
|
} |
|
||||||
|
|
|
|
||||||
|
@ -336,7 +336,7 @@ Shadow DOM provides an encapsulation for components, so as a general rule it doe
|
||||||
})
|
})
|
||||||
class Kid {
|
class Kid {
|
||||||
constructor(
|
constructor(
|
||||||
@Ancestor() dad:Dad,
|
@SkipSelf() dad:Dad,
|
||||||
@Optional() grandpa:Grandpa
|
@Optional() grandpa:Grandpa
|
||||||
) {
|
) {
|
||||||
this.name = 'Billy';
|
this.name = 'Billy';
|
||||||
|
@ -353,7 +353,7 @@ class Kid {
|
||||||
directives: [Kid]
|
directives: [Kid]
|
||||||
})
|
})
|
||||||
class Dad {
|
class Dad {
|
||||||
constructor(@Ancestor() dad:Grandpa) {
|
constructor(@SkipSelf() dad:Grandpa) {
|
||||||
this.name = 'Joe Jr';
|
this.name = 'Joe Jr';
|
||||||
this.dad = dad.name;
|
this.dad = dad.name;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {ListWrapper, isListLikeIterable, StringMapWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper, isListLikeIterable, StringMapWrapper} from 'angular2/src/facade/collection';
|
||||||
import {isBlank, isPresent, BaseException, CONST} from 'angular2/src/facade/lang';
|
import {isBlank, isPresent, BaseException, CONST} from 'angular2/src/facade/lang';
|
||||||
import {Pipe, PipeFactory} from './pipe';
|
import {Pipe, PipeFactory} from './pipe';
|
||||||
import {Injectable, UnboundedMetadata, OptionalMetadata} from 'angular2/di';
|
import {Injectable, OptionalMetadata, SkipSelfMetadata} from 'angular2/di';
|
||||||
import {ChangeDetectorRef} from '../change_detector_ref';
|
import {ChangeDetectorRef} from '../change_detector_ref';
|
||||||
import {Binding} from 'angular2/di';
|
import {Binding} from 'angular2/di';
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ export class Pipes {
|
||||||
return Pipes.create(config, pipes);
|
return Pipes.create(config, pipes);
|
||||||
},
|
},
|
||||||
// Dependency technically isn't optional, but we can provide a better error message this way.
|
// Dependency technically isn't optional, but we can provide a better error message this way.
|
||||||
deps: [[Pipes, new UnboundedMetadata(), new OptionalMetadata()]]
|
deps: [[Pipes, new SkipSelfMetadata(), new OptionalMetadata()]]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,9 @@ import {DEFAULT} from 'angular2/change_detection';
|
||||||
*
|
*
|
||||||
* To inject other directives, declare the constructor parameter as:
|
* To inject other directives, declare the constructor parameter as:
|
||||||
* - `directive:DirectiveType`: a directive on the current element only
|
* - `directive:DirectiveType`: a directive on the current element only
|
||||||
* - `@Ancestor() directive:DirectiveType`: any directive that matches the type between the current
|
* - `@Host() directive:DirectiveType`: any directive that matches the type between the current
|
||||||
* element and the
|
* element and the
|
||||||
* Shadow DOM root. Current element is not included in the resolution, therefore even if it could
|
* Shadow DOM root.
|
||||||
* resolve it, it will
|
|
||||||
* be ignored.
|
|
||||||
* - `@Query(DirectiveType) query:QueryList<DirectiveType>`: A live collection of direct child
|
* - `@Query(DirectiveType) query:QueryList<DirectiveType>`: A live collection of direct child
|
||||||
* directives.
|
* directives.
|
||||||
* - `@QueryDescendants(DirectiveType) query:QueryList<DirectiveType>`: A live collection of any
|
* - `@QueryDescendants(DirectiveType) query:QueryList<DirectiveType>`: A live collection of any
|
||||||
|
@ -164,21 +162,19 @@ import {DEFAULT} from 'angular2/change_detection';
|
||||||
* ### Injecting a directive from any ancestor elements
|
* ### Injecting a directive from any ancestor elements
|
||||||
*
|
*
|
||||||
* Directives can inject other directives declared on any ancestor element (in the current Shadow
|
* Directives can inject other directives declared on any ancestor element (in the current Shadow
|
||||||
* DOM), i.e. on the
|
* DOM), i.e. on the current element, the
|
||||||
* parent element and its parents. By definition, a directive with an `@Ancestor` annotation does
|
* parent element, or its parents.
|
||||||
* not attempt to
|
|
||||||
* resolve dependencies for the current element, even if this would satisfy the dependency.
|
|
||||||
*
|
|
||||||
* ```
|
* ```
|
||||||
* @Directive({ selector: '[my-directive]' })
|
* @Directive({ selector: '[my-directive]' })
|
||||||
* class MyDirective {
|
* class MyDirective {
|
||||||
* constructor(@Ancestor() dependency: Dependency) {
|
* constructor(@Host() dependency: Dependency) {
|
||||||
* expect(dependency.id).toEqual(2);
|
* expect(dependency.id).toEqual(2);
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* `@Ancestor` checks the parent, as well as its parents recursively. If `dependency="2"` didn't
|
* `@Host` checks the current element, the parent, as well as its parents recursively. If
|
||||||
|
* `dependency="2"` didn't
|
||||||
* exist on the direct parent, this injection would
|
* exist on the direct parent, this injection would
|
||||||
* have returned
|
* have returned
|
||||||
* `dependency="1"`.
|
* `dependency="1"`.
|
||||||
|
|
|
@ -25,7 +25,6 @@ import {
|
||||||
AbstractBindingError,
|
AbstractBindingError,
|
||||||
CyclicDependencyError,
|
CyclicDependencyError,
|
||||||
resolveForwardRef,
|
resolveForwardRef,
|
||||||
VisibilityMetadata,
|
|
||||||
DependencyProvider
|
DependencyProvider
|
||||||
} from 'angular2/di';
|
} from 'angular2/di';
|
||||||
import {
|
import {
|
||||||
|
@ -167,9 +166,10 @@ export class TreeNode<T extends TreeNode<any>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DirectiveDependency extends Dependency {
|
export class DirectiveDependency extends Dependency {
|
||||||
constructor(key: Key, optional: boolean, visibility: any, properties: List<any>,
|
constructor(key: Key, optional: boolean, lowerBoundVisibility: Object,
|
||||||
public attributeName: string, public queryDecorator: Query) {
|
upperBoundVisibility: Object, properties: List<any>, public attributeName: string,
|
||||||
super(key, optional, visibility, properties);
|
public queryDecorator: Query) {
|
||||||
|
super(key, optional, lowerBoundVisibility, upperBoundVisibility, properties);
|
||||||
this._verify();
|
this._verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,9 +183,9 @@ export class DirectiveDependency extends Dependency {
|
||||||
}
|
}
|
||||||
|
|
||||||
static createFrom(d: Dependency): Dependency {
|
static createFrom(d: Dependency): Dependency {
|
||||||
return new DirectiveDependency(d.key, d.optional, d.visibility, d.properties,
|
return new DirectiveDependency(
|
||||||
DirectiveDependency._attributeName(d.properties),
|
d.key, d.optional, d.lowerBoundVisibility, d.upperBoundVisibility, d.properties,
|
||||||
DirectiveDependency._query(d.properties));
|
DirectiveDependency._attributeName(d.properties), DirectiveDependency._query(d.properties));
|
||||||
}
|
}
|
||||||
|
|
||||||
static _attributeName(properties): string {
|
static _attributeName(properties): string {
|
||||||
|
|
|
@ -14,9 +14,10 @@ import {Key} from './key';
|
||||||
import {
|
import {
|
||||||
InjectMetadata,
|
InjectMetadata,
|
||||||
InjectableMetadata,
|
InjectableMetadata,
|
||||||
VisibilityMetadata,
|
|
||||||
OptionalMetadata,
|
OptionalMetadata,
|
||||||
DEFAULT_VISIBILITY,
|
SelfMetadata,
|
||||||
|
HostMetadata,
|
||||||
|
SkipSelfMetadata,
|
||||||
DependencyMetadata
|
DependencyMetadata
|
||||||
} from './metadata';
|
} from './metadata';
|
||||||
import {NoAnnotationError} from './exceptions';
|
import {NoAnnotationError} from './exceptions';
|
||||||
|
@ -26,12 +27,10 @@ import {resolveForwardRef} from './forward_ref';
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export class Dependency {
|
export class Dependency {
|
||||||
constructor(public key: Key, public optional: boolean, public visibility: VisibilityMetadata,
|
constructor(public key: Key, public optional: boolean, public lowerBoundVisibility: any,
|
||||||
public properties: List<any>) {}
|
public upperBoundVisibility: any, public properties: List<any>) {}
|
||||||
|
|
||||||
static fromKey(key: Key): Dependency {
|
static fromKey(key: Key): Dependency { return new Dependency(key, false, null, null, []); }
|
||||||
return new Dependency(key, false, DEFAULT_VISIBILITY, []);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const _EMPTY_LIST = CONST_EXPR([]);
|
const _EMPTY_LIST = CONST_EXPR([]);
|
||||||
|
@ -390,50 +389,61 @@ function _dependenciesFor(typeOrFunc): List<Dependency> {
|
||||||
return ListWrapper.map(params, (p: List<any>) => _extractToken(typeOrFunc, p, params));
|
return ListWrapper.map(params, (p: List<any>) => _extractToken(typeOrFunc, p, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
function _extractToken(typeOrFunc, annotations /*List<any> | any*/, params: List<List<any>>):
|
function _extractToken(typeOrFunc, metadata /*List<any> | any*/, params: List<List<any>>):
|
||||||
Dependency {
|
Dependency {
|
||||||
var depProps = [];
|
var depProps = [];
|
||||||
var token = null;
|
var token = null;
|
||||||
var optional = false;
|
var optional = false;
|
||||||
|
|
||||||
if (!isArray(annotations)) {
|
if (!isArray(metadata)) {
|
||||||
return _createDependency(annotations, optional, DEFAULT_VISIBILITY, depProps);
|
return _createDependency(metadata, optional, null, null, depProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
var visibility = DEFAULT_VISIBILITY;
|
var lowerBoundVisibility = null;
|
||||||
|
;
|
||||||
|
var upperBoundVisibility = null;
|
||||||
|
;
|
||||||
|
|
||||||
for (var i = 0; i < annotations.length; ++i) {
|
for (var i = 0; i < metadata.length; ++i) {
|
||||||
var paramAnnotation = annotations[i];
|
var paramMetadata = metadata[i];
|
||||||
|
|
||||||
if (paramAnnotation instanceof Type) {
|
if (paramMetadata instanceof Type) {
|
||||||
token = paramAnnotation;
|
token = paramMetadata;
|
||||||
|
|
||||||
} else if (paramAnnotation instanceof InjectMetadata) {
|
} else if (paramMetadata instanceof InjectMetadata) {
|
||||||
token = paramAnnotation.token;
|
token = paramMetadata.token;
|
||||||
|
|
||||||
} else if (paramAnnotation instanceof OptionalMetadata) {
|
} else if (paramMetadata instanceof OptionalMetadata) {
|
||||||
optional = true;
|
optional = true;
|
||||||
|
|
||||||
} else if (paramAnnotation instanceof VisibilityMetadata) {
|
} else if (paramMetadata instanceof SelfMetadata) {
|
||||||
visibility = paramAnnotation;
|
upperBoundVisibility = paramMetadata;
|
||||||
|
|
||||||
} else if (paramAnnotation instanceof DependencyMetadata) {
|
} else if (paramMetadata instanceof HostMetadata) {
|
||||||
if (isPresent(paramAnnotation.token)) {
|
upperBoundVisibility = paramMetadata;
|
||||||
token = paramAnnotation.token;
|
|
||||||
|
} else if (paramMetadata instanceof SkipSelfMetadata) {
|
||||||
|
lowerBoundVisibility = paramMetadata;
|
||||||
|
|
||||||
|
} else if (paramMetadata instanceof DependencyMetadata) {
|
||||||
|
if (isPresent(paramMetadata.token)) {
|
||||||
|
token = paramMetadata.token;
|
||||||
}
|
}
|
||||||
depProps.push(paramAnnotation);
|
depProps.push(paramMetadata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
token = resolveForwardRef(token);
|
token = resolveForwardRef(token);
|
||||||
|
|
||||||
if (isPresent(token)) {
|
if (isPresent(token)) {
|
||||||
return _createDependency(token, optional, visibility, depProps);
|
return _createDependency(token, optional, lowerBoundVisibility, upperBoundVisibility, depProps);
|
||||||
} else {
|
} else {
|
||||||
throw new NoAnnotationError(typeOrFunc, params);
|
throw new NoAnnotationError(typeOrFunc, params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _createDependency(token, optional, visibility, depProps): Dependency {
|
function _createDependency(token, optional, lowerBoundVisibility, upperBoundVisibility, depProps):
|
||||||
return new Dependency(Key.get(token), optional, visibility, depProps);
|
Dependency {
|
||||||
|
return new Dependency(Key.get(token), optional, lowerBoundVisibility, upperBoundVisibility,
|
||||||
|
depProps);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,15 +32,15 @@ class Self extends SelfMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AncestorMetadata}.
|
* {@link HostMetadata}.
|
||||||
*/
|
*/
|
||||||
class Ancestor extends AncestorMetadata {
|
class Host extends HostMetadata {
|
||||||
const Ancestor({bool self}) : super(self: self);
|
const Host() : super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link UnboundedMetadata}.
|
* {@link SkipSelfMetadata}.
|
||||||
*/
|
*/
|
||||||
class Unbounded extends UnboundedMetadata {
|
class SkipSelf extends SkipSelfMetadata {
|
||||||
const Unbounded({bool self}) : super(self: self);
|
const SkipSelf() : super();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,8 @@ import {
|
||||||
OptionalMetadata,
|
OptionalMetadata,
|
||||||
InjectableMetadata,
|
InjectableMetadata,
|
||||||
SelfMetadata,
|
SelfMetadata,
|
||||||
VisibilityMetadata,
|
HostMetadata,
|
||||||
AncestorMetadata,
|
SkipSelfMetadata
|
||||||
UnboundedMetadata
|
|
||||||
} from './metadata';
|
} from './metadata';
|
||||||
import {makeDecorator, makeParamDecorator, TypeDecorator} from '../util/decorators';
|
import {makeDecorator, makeParamDecorator, TypeDecorator} from '../util/decorators';
|
||||||
|
|
||||||
|
@ -42,19 +41,19 @@ export interface SelfFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for creating {@link AncestorMetadata}.
|
* Factory for creating {@link HostMetadata}.
|
||||||
*/
|
*/
|
||||||
export interface AncestorFactory {
|
export interface HostFactory {
|
||||||
(visibility?: {self: boolean}): any;
|
(): any;
|
||||||
new (visibility?: {self: boolean}): AncestorMetadata;
|
new (): HostMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for creating {@link UnboundedMetadata}.
|
* Factory for creating {@link SkipSelfMetadata}.
|
||||||
*/
|
*/
|
||||||
export interface UnboundedFactory {
|
export interface SkipSelfFactory {
|
||||||
(visibility?: {self: boolean}): any;
|
(): any;
|
||||||
new (visibility?: {self: boolean}): UnboundedMetadata;
|
new (): SkipSelfMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,11 +77,11 @@ export var Injectable: InjectableFactory = <InjectableFactory>makeDecorator(Inje
|
||||||
export var Self: SelfFactory = makeParamDecorator(SelfMetadata);
|
export var Self: SelfFactory = makeParamDecorator(SelfMetadata);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for creating {@link AncestorMetadata}.
|
* Factory for creating {@link HostMetadata}.
|
||||||
*/
|
*/
|
||||||
export var Ancestor: AncestorFactory = makeParamDecorator(AncestorMetadata);
|
export var Host: HostFactory = makeParamDecorator(HostMetadata);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory for creating {@link UnboundedMetadata}.
|
* Factory for creating {@link SkipSelfMetadata}.
|
||||||
*/
|
*/
|
||||||
export var Unbounded: UnboundedFactory = makeParamDecorator(UnboundedMetadata);
|
export var SkipSelf: SkipSelfFactory = makeParamDecorator(SkipSelfMetadata);
|
|
@ -13,7 +13,7 @@ import {
|
||||||
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
|
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
import {Key} from './key';
|
import {Key} from './key';
|
||||||
import {resolveForwardRef} from './forward_ref';
|
import {resolveForwardRef} from './forward_ref';
|
||||||
import {VisibilityMetadata, DEFAULT_VISIBILITY, SelfMetadata, AncestorMetadata} from './metadata';
|
import {SelfMetadata, HostMetadata, SkipSelfMetadata} from './metadata';
|
||||||
|
|
||||||
const _constructing = CONST_EXPR(new Object());
|
const _constructing = CONST_EXPR(new Object());
|
||||||
const _notFound = CONST_EXPR(new Object());
|
const _notFound = CONST_EXPR(new Object());
|
||||||
|
@ -192,7 +192,7 @@ export interface InjectorStrategy {
|
||||||
getObjAtIndex(index: number): any;
|
getObjAtIndex(index: number): any;
|
||||||
getMaxNumberOfObjects(): number;
|
getMaxNumberOfObjects(): number;
|
||||||
|
|
||||||
attach(parent: Injector, isBoundary: boolean): void;
|
attach(parent: Injector, isHost: boolean): void;
|
||||||
resetConstructionCounter(): void;
|
resetConstructionCounter(): void;
|
||||||
instantiateBinding(binding: ResolvedBinding, visibility: number): any;
|
instantiateBinding(binding: ResolvedBinding, visibility: number): any;
|
||||||
}
|
}
|
||||||
|
@ -217,10 +217,10 @@ export class InjectorInlineStrategy implements InjectorStrategy {
|
||||||
return this.injector._new(binding, visibility);
|
return this.injector._new(binding, visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
attach(parent: Injector, isBoundary: boolean): void {
|
attach(parent: Injector, isHost: boolean): void {
|
||||||
var inj = this.injector;
|
var inj = this.injector;
|
||||||
inj._parent = parent;
|
inj._parent = parent;
|
||||||
inj._isBoundary = isBoundary;
|
inj._isHost = isHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
getObjByKeyId(keyId: number, visibility: number): any {
|
getObjByKeyId(keyId: number, visibility: number): any {
|
||||||
|
@ -323,10 +323,10 @@ export class InjectorDynamicStrategy implements InjectorStrategy {
|
||||||
return this.injector._new(binding, visibility);
|
return this.injector._new(binding, visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
attach(parent: Injector, isBoundary: boolean): void {
|
attach(parent: Injector, isHost: boolean): void {
|
||||||
var inj = this.injector;
|
var inj = this.injector;
|
||||||
inj._parent = parent;
|
inj._parent = parent;
|
||||||
inj._isBoundary = isBoundary;
|
inj._isHost = isHost;
|
||||||
}
|
}
|
||||||
|
|
||||||
getObjByKeyId(keyId: number, visibility: number): any {
|
getObjByKeyId(keyId: number, visibility: number): any {
|
||||||
|
@ -466,7 +466,7 @@ export class Injector {
|
||||||
}
|
}
|
||||||
|
|
||||||
_strategy: InjectorStrategy;
|
_strategy: InjectorStrategy;
|
||||||
_isBoundary: boolean = false;
|
_isHost: boolean = false;
|
||||||
_constructionCounter: number = 0;
|
_constructionCounter: number = 0;
|
||||||
|
|
||||||
constructor(public _proto: ProtoInjector, public _parent: Injector = null,
|
constructor(public _proto: ProtoInjector, public _parent: Injector = null,
|
||||||
|
@ -490,7 +490,7 @@ export class Injector {
|
||||||
* @returns an instance represented by the token. Throws if not found.
|
* @returns an instance represented by the token. Throws if not found.
|
||||||
*/
|
*/
|
||||||
get(token: any): any {
|
get(token: any): any {
|
||||||
return this._getByKey(Key.get(token), DEFAULT_VISIBILITY, false, PUBLIC_AND_PRIVATE);
|
return this._getByKey(Key.get(token), null, null, false, PUBLIC_AND_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -500,7 +500,7 @@ export class Injector {
|
||||||
* @returns an instance represented by the token. Returns `null` if not found.
|
* @returns an instance represented by the token. Returns `null` if not found.
|
||||||
*/
|
*/
|
||||||
getOptional(token: any): any {
|
getOptional(token: any): any {
|
||||||
return this._getByKey(Key.get(token), DEFAULT_VISIBILITY, true, PUBLIC_AND_PRIVATE);
|
return this._getByKey(Key.get(token), null, null, true, PUBLIC_AND_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -679,24 +679,25 @@ export class Injector {
|
||||||
if (special !== undefinedValue) {
|
if (special !== undefinedValue) {
|
||||||
return special;
|
return special;
|
||||||
} else {
|
} else {
|
||||||
return this._getByKey(dep.key, dep.visibility, dep.optional, bindingVisibility);
|
return this._getByKey(dep.key, dep.lowerBoundVisibility, dep.upperBoundVisibility,
|
||||||
|
dep.optional, bindingVisibility);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getByKey(key: Key, depVisibility: VisibilityMetadata, optional: boolean,
|
private _getByKey(key: Key, lowerBoundVisibility: Object, upperBoundVisibility: Object,
|
||||||
bindingVisibility: number): any {
|
optional: boolean, bindingVisibility: number): any {
|
||||||
if (key === INJECTOR_KEY) {
|
if (key === INJECTOR_KEY) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (depVisibility instanceof SelfMetadata) {
|
if (upperBoundVisibility instanceof SelfMetadata) {
|
||||||
return this._getByKeySelf(key, optional, bindingVisibility);
|
return this._getByKeySelf(key, optional, bindingVisibility);
|
||||||
|
|
||||||
} else if (depVisibility instanceof AncestorMetadata) {
|
} else if (upperBoundVisibility instanceof HostMetadata) {
|
||||||
return this._getByKeyAncestor(key, optional, bindingVisibility, depVisibility.includeSelf);
|
return this._getByKeyHost(key, optional, bindingVisibility, lowerBoundVisibility);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return this._getByKeyUnbounded(key, optional, bindingVisibility, depVisibility.includeSelf);
|
return this._getByKeyDefault(key, optional, bindingVisibility, lowerBoundVisibility);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,12 +714,12 @@ export class Injector {
|
||||||
return (obj !== undefinedValue) ? obj : this._throwOrNull(key, optional);
|
return (obj !== undefinedValue) ? obj : this._throwOrNull(key, optional);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getByKeyAncestor(key: Key, optional: boolean, bindingVisibility: number,
|
_getByKeyHost(key: Key, optional: boolean, bindingVisibility: number,
|
||||||
includeSelf: boolean): any {
|
lowerBoundVisibility: Object): any {
|
||||||
var inj = this;
|
var inj = this;
|
||||||
|
|
||||||
if (!includeSelf) {
|
if (lowerBoundVisibility instanceof SkipSelfMetadata) {
|
||||||
if (inj._isBoundary) {
|
if (inj._isHost) {
|
||||||
return this._getPrivateDependency(key, optional, inj);
|
return this._getPrivateDependency(key, optional, inj);
|
||||||
} else {
|
} else {
|
||||||
inj = inj._parent;
|
inj = inj._parent;
|
||||||
|
@ -729,7 +730,7 @@ export class Injector {
|
||||||
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
|
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
|
||||||
if (obj !== undefinedValue) return obj;
|
if (obj !== undefinedValue) return obj;
|
||||||
|
|
||||||
if (isPresent(inj._parent) && inj._isBoundary) {
|
if (isPresent(inj._parent) && inj._isHost) {
|
||||||
return this._getPrivateDependency(key, optional, inj);
|
return this._getPrivateDependency(key, optional, inj);
|
||||||
} else {
|
} else {
|
||||||
inj = inj._parent;
|
inj = inj._parent;
|
||||||
|
@ -744,11 +745,12 @@ export class Injector {
|
||||||
return (obj !== undefinedValue) ? obj : this._throwOrNull(key, optional);
|
return (obj !== undefinedValue) ? obj : this._throwOrNull(key, optional);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getByKeyUnbounded(key: Key, optional: boolean, bindingVisibility: number,
|
_getByKeyDefault(key: Key, optional: boolean, bindingVisibility: number,
|
||||||
includeSelf: boolean): any {
|
lowerBoundVisibility: Object): any {
|
||||||
var inj = this;
|
var inj = this;
|
||||||
if (!includeSelf) {
|
|
||||||
bindingVisibility = inj._isBoundary ? PUBLIC_AND_PRIVATE : PUBLIC;
|
if (lowerBoundVisibility instanceof SkipSelfMetadata) {
|
||||||
|
bindingVisibility = inj._isHost ? PUBLIC_AND_PRIVATE : PUBLIC;
|
||||||
inj = inj._parent;
|
inj = inj._parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +758,7 @@ export class Injector {
|
||||||
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
|
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
|
||||||
if (obj !== undefinedValue) return obj;
|
if (obj !== undefinedValue) return obj;
|
||||||
|
|
||||||
bindingVisibility = inj._isBoundary ? PUBLIC_AND_PRIVATE : PUBLIC;
|
bindingVisibility = inj._isHost ? PUBLIC_AND_PRIVATE : PUBLIC;
|
||||||
inj = inj._parent;
|
inj = inj._parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,22 +82,6 @@ export class InjectableMetadata {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies how injector should resolve a dependency.
|
|
||||||
*
|
|
||||||
* See {@link Self}, {@link Ancestor}, {@link Unbounded}.
|
|
||||||
*/
|
|
||||||
@CONST()
|
|
||||||
export class VisibilityMetadata {
|
|
||||||
constructor(public crossBoundaries: boolean, public _includeSelf: boolean) {}
|
|
||||||
|
|
||||||
get includeSelf(): boolean { return isBlank(this._includeSelf) ? false : this._includeSelf; }
|
|
||||||
|
|
||||||
toString(): string {
|
|
||||||
return `@Visibility(crossBoundaries: ${this.crossBoundaries}, includeSelf: ${this.includeSelf}})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies that an injector should retrieve a dependency from itself.
|
* Specifies that an injector should retrieve a dependency from itself.
|
||||||
*
|
*
|
||||||
|
@ -117,50 +101,45 @@ export class VisibilityMetadata {
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
export class SelfMetadata extends VisibilityMetadata {
|
export class SelfMetadata {
|
||||||
constructor() { super(false, true); }
|
|
||||||
toString(): string { return `@Self()`; }
|
toString(): string { return `@Self()`; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies that an injector should retrieve a dependency from any ancestor from the same boundary.
|
* Specifies that the dependency resolution should start from the parent injector.
|
||||||
*
|
*
|
||||||
* ## Example
|
* ## Example
|
||||||
*
|
*
|
||||||
|
*
|
||||||
* ```
|
* ```
|
||||||
* class Dependency {
|
* class Service {}
|
||||||
|
*
|
||||||
|
* class ParentService implements Service {
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* class NeedsDependency {
|
* class ChildService implements Service {
|
||||||
* constructor(public @Ancestor() dependency:Dependency) {}
|
* constructor(public @SkipSelf() parentService:Service) {}
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* var parent = Injector.resolveAndCreate([
|
* var parent = Injector.resolveAndCreate([
|
||||||
* bind(Dependency).toClass(AncestorDependency)
|
* bind(Service).toClass(ParentService)
|
||||||
* ]);
|
* ]);
|
||||||
* var child = parent.resolveAndCreateChild([]);
|
* var child = parent.resolveAndCreateChild([
|
||||||
* var grandChild = child.resolveAndCreateChild([NeedsDependency, Depedency]);
|
* bind(Service).toClass(ChildSerice)
|
||||||
* var nd = grandChild.get(NeedsDependency);
|
* ]);
|
||||||
* expect(nd.dependency).toBeAnInstanceOf(AncestorDependency);
|
* var s = child.get(Service);
|
||||||
* ```
|
* expect(s).toBeAnInstanceOf(ChildService);
|
||||||
*
|
* expect(s.parentService).toBeAnInstanceOf(ParentService);
|
||||||
* You can make an injector to retrive a dependency either from itself or its ancestor by setting
|
|
||||||
* self to true.
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* class NeedsDependency {
|
|
||||||
* constructor(public @Ancestor({self:true}) dependency:Dependency) {}
|
|
||||||
* }
|
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
export class AncestorMetadata extends VisibilityMetadata {
|
export class SkipSelfMetadata {
|
||||||
constructor({self}: {self?: boolean} = {}) { super(false, self); }
|
toString(): string { return `@SkipSelf()`; }
|
||||||
toString(): string { return `@Ancestor(self: ${this.includeSelf}})`; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies that an injector should retrieve a dependency from any ancestor, crossing boundaries.
|
* Specifies that an injector should retrieve a dependency from any injector until reaching the
|
||||||
|
* closest host.
|
||||||
*
|
*
|
||||||
* ## Example
|
* ## Example
|
||||||
*
|
*
|
||||||
|
@ -169,32 +148,20 @@ export class AncestorMetadata extends VisibilityMetadata {
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* class NeedsDependency {
|
* class NeedsDependency {
|
||||||
* constructor(public @Ancestor() dependency:Dependency) {}
|
* constructor(public @Host() dependency:Dependency) {}
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* var parent = Injector.resolveAndCreate([
|
* var parent = Injector.resolveAndCreate([
|
||||||
* bind(Dependency).toClass(AncestorDependency)
|
* bind(Dependency).toClass(HostDependency)
|
||||||
* ]);
|
* ]);
|
||||||
* var child = parent.resolveAndCreateChild([]);
|
* var child = parent.resolveAndCreateChild([]);
|
||||||
* var grandChild = child.resolveAndCreateChild([NeedsDependency, Depedency]);
|
* var grandChild = child.resolveAndCreateChild([NeedsDependency, Depedency]);
|
||||||
* var nd = grandChild.get(NeedsDependency);
|
* var nd = grandChild.get(NeedsDependency);
|
||||||
* expect(nd.dependency).toBeAnInstanceOf(AncestorDependency);
|
* expect(nd.dependency).toBeAnInstanceOf(HostDependency);
|
||||||
* ```
|
* ```
|
||||||
*
|
|
||||||
* You can make an injector to retrive a dependency either from itself or its ancestor by setting
|
|
||||||
* self to true.
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* class NeedsDependency {
|
|
||||||
* constructor(public @Ancestor({self:true}) dependency:Dependency) {}
|
|
||||||
* }
|
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
@CONST()
|
@CONST()
|
||||||
export class UnboundedMetadata extends VisibilityMetadata {
|
export class HostMetadata {
|
||||||
constructor({self}: {self?: boolean} = {}) { super(true, self); }
|
toString(): string { return `@Host()`; }
|
||||||
toString(): string { return `@Unbounded(self: ${this.includeSelf}})`; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_VISIBILITY: VisibilityMetadata =
|
|
||||||
CONST_EXPR(new UnboundedMetadata({self: true}));
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {Directive} from 'angular2/annotations';
|
import {Directive} from 'angular2/annotations';
|
||||||
import {Ancestor} from 'angular2/di';
|
import {Host} from 'angular2/di';
|
||||||
import {ViewContainerRef, TemplateRef} from 'angular2/core';
|
import {ViewContainerRef, TemplateRef} from 'angular2/core';
|
||||||
import {isPresent, isBlank, normalizeBlank} from 'angular2/src/facade/lang';
|
import {isPresent, isBlank, normalizeBlank} from 'angular2/src/facade/lang';
|
||||||
import {ListWrapper, List, MapWrapper, Map} from 'angular2/src/facade/collection';
|
import {ListWrapper, List, MapWrapper, Map} from 'angular2/src/facade/collection';
|
||||||
|
@ -157,7 +157,7 @@ export class NgSwitchWhen {
|
||||||
_view: SwitchView;
|
_view: SwitchView;
|
||||||
|
|
||||||
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef,
|
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef,
|
||||||
@Ancestor() sswitch: NgSwitch) {
|
@Host() sswitch: NgSwitch) {
|
||||||
// `_whenDefault` is used as a marker for a not yet initialized value
|
// `_whenDefault` is used as a marker for a not yet initialized value
|
||||||
this._value = _whenDefault;
|
this._value = _whenDefault;
|
||||||
this._switch = sswitch;
|
this._switch = sswitch;
|
||||||
|
@ -187,7 +187,7 @@ export class NgSwitchWhen {
|
||||||
@Directive({selector: '[ng-switch-default]'})
|
@Directive({selector: '[ng-switch-default]'})
|
||||||
export class NgSwitchDefault {
|
export class NgSwitchDefault {
|
||||||
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef,
|
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef,
|
||||||
@Ancestor() sswitch: NgSwitch) {
|
@Host() sswitch: NgSwitch) {
|
||||||
sswitch._registerView(_whenDefault, new SwitchView(viewContainer, templateRef));
|
sswitch._registerView(_whenDefault, new SwitchView(viewContainer, templateRef));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {Directive, LifecycleEvent} from 'angular2/annotations';
|
import {Directive, LifecycleEvent} from 'angular2/annotations';
|
||||||
import {Inject, Ancestor, forwardRef, Binding} from 'angular2/di';
|
import {Inject, Host, SkipSelf, forwardRef, Binding} from 'angular2/di';
|
||||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
import {CONST_EXPR} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ const controlGroupBinding =
|
||||||
})
|
})
|
||||||
export class NgControlGroup extends ControlContainer {
|
export class NgControlGroup extends ControlContainer {
|
||||||
_parent: ControlContainer;
|
_parent: ControlContainer;
|
||||||
constructor(@Ancestor() _parent: ControlContainer) {
|
constructor(@Host() @SkipSelf() _parent: ControlContainer) {
|
||||||
super();
|
super();
|
||||||
this._parent = _parent;
|
this._parent = _parent;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {List, StringMap} from 'angular2/src/facade/collection';
|
||||||
|
|
||||||
import {QueryList} from 'angular2/core';
|
import {QueryList} from 'angular2/core';
|
||||||
import {Query, Directive, LifecycleEvent} from 'angular2/annotations';
|
import {Query, Directive, LifecycleEvent} from 'angular2/annotations';
|
||||||
import {forwardRef, Ancestor, Binding, Inject} from 'angular2/di';
|
import {forwardRef, Host, SkipSelf, Binding, Inject} from 'angular2/di';
|
||||||
|
|
||||||
import {ControlContainer} from './control_container';
|
import {ControlContainer} from './control_container';
|
||||||
import {NgControl} from './ng_control';
|
import {NgControl} from './ng_control';
|
||||||
|
@ -88,7 +88,7 @@ export class NgControlName extends NgControl {
|
||||||
_added = false;
|
_added = false;
|
||||||
|
|
||||||
// Scope the query once https://github.com/angular/angular/issues/2603 is fixed
|
// Scope the query once https://github.com/angular/angular/issues/2603 is fixed
|
||||||
constructor(@Ancestor() parent: ControlContainer,
|
constructor(@Host() @SkipSelf() parent: ControlContainer,
|
||||||
@Query(NgValidator) ngValidators: QueryList<NgValidator>) {
|
@Query(NgValidator) ngValidators: QueryList<NgValidator>) {
|
||||||
super();
|
super();
|
||||||
this._parent = parent;
|
this._parent = parent;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
import {QueryList} from 'angular2/core';
|
import {QueryList} from 'angular2/core';
|
||||||
import {Query, Directive, LifecycleEvent} from 'angular2/annotations';
|
import {Query, Directive, LifecycleEvent} from 'angular2/annotations';
|
||||||
import {forwardRef, Ancestor, Binding} from 'angular2/di';
|
import {forwardRef, Binding} from 'angular2/di';
|
||||||
|
|
||||||
import {NgControl} from './ng_control';
|
import {NgControl} from './ng_control';
|
||||||
import {Control} from '../model';
|
import {Control} from '../model';
|
||||||
|
|
|
@ -3,7 +3,7 @@ import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
import {QueryList} from 'angular2/core';
|
import {QueryList} from 'angular2/core';
|
||||||
import {Query, Directive, LifecycleEvent} from 'angular2/annotations';
|
import {Query, Directive, LifecycleEvent} from 'angular2/annotations';
|
||||||
import {forwardRef, Ancestor, Binding} from 'angular2/di';
|
import {forwardRef, Binding} from 'angular2/di';
|
||||||
|
|
||||||
import {NgControl} from './ng_control';
|
import {NgControl} from './ng_control';
|
||||||
import {Control} from '../model';
|
import {Control} from '../model';
|
||||||
|
|
|
@ -40,7 +40,7 @@ import {
|
||||||
Directive,
|
Directive,
|
||||||
LifecycleEvent
|
LifecycleEvent
|
||||||
} from 'angular2/annotations';
|
} from 'angular2/annotations';
|
||||||
import {bind, Injector, Binding, Optional, Inject, Injectable, Self, Ancestor, Unbounded, InjectMetadata, AncestorMetadata} from 'angular2/di';
|
import {bind, Injector, Binding, Optional, Inject, Injectable, Self, SkipSelf, InjectMetadata, Host, HostMetadata, SkipSelfMetadata} from 'angular2/di';
|
||||||
import {AppProtoView, AppView} from 'angular2/src/core/compiler/view';
|
import {AppProtoView, AppView} from 'angular2/src/core/compiler/view';
|
||||||
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
|
||||||
import {TemplateRef} from 'angular2/src/core/compiler/template_ref';
|
import {TemplateRef} from 'angular2/src/core/compiler/template_ref';
|
||||||
|
@ -103,15 +103,15 @@ class OptionallyNeedsDirective {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class NeedsDirectiveFromAncestor {
|
class NeeedsDirectiveFromHost {
|
||||||
dependency: SimpleDirective;
|
dependency: SimpleDirective;
|
||||||
constructor(@Ancestor() dependency: SimpleDirective) { this.dependency = dependency; }
|
constructor(@Host() dependency: SimpleDirective) { this.dependency = dependency; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class NeedsDirectiveFromAnAncestorShadowDom {
|
class NeedsDirectiveFromHostShadowDom {
|
||||||
dependency: SimpleDirective;
|
dependency: SimpleDirective;
|
||||||
constructor(@Unbounded() dependency: SimpleDirective) { this.dependency = dependency; }
|
constructor(dependency: SimpleDirective) { this.dependency = dependency; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -121,9 +121,9 @@ class NeedsService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class NeedsAncestorService {
|
class NeedsServiceFromHost {
|
||||||
service: any;
|
service: any;
|
||||||
constructor(@Ancestor() @Inject("service") service) { this.service = service; }
|
constructor(@Host() @Inject("service") service) { this.service = service; }
|
||||||
}
|
}
|
||||||
|
|
||||||
class HasEventEmitter {
|
class HasEventEmitter {
|
||||||
|
@ -597,7 +597,7 @@ export function main() {
|
||||||
bind('injectable2')
|
bind('injectable2')
|
||||||
.toFactory(
|
.toFactory(
|
||||||
(val) => `${val}-injectable2`,
|
(val) => `${val}-injectable2`,
|
||||||
[[new InjectMetadata('injectable1'), new AncestorMetadata()]])
|
[[new InjectMetadata('injectable1'), new SkipSelfMetadata()]])
|
||||||
]
|
]
|
||||||
}))]);
|
}))]);
|
||||||
expect(childInj.get('injectable2')).toEqual('injectable1-injectable2');
|
expect(childInj.get('injectable2')).toEqual('injectable1-injectable2');
|
||||||
|
@ -710,25 +710,25 @@ export function main() {
|
||||||
var inj = injector([NeedsService], imperativelyCreatedInjector);
|
var inj = injector([NeedsService], imperativelyCreatedInjector);
|
||||||
expect(inj.get(NeedsService).service).toEqual('appService');
|
expect(inj.get(NeedsService).service).toEqual('appService');
|
||||||
|
|
||||||
expect(() => injector([NeedsAncestorService], imperativelyCreatedInjector)).toThrowError();
|
expect(() => injector([NeedsServiceFromHost], imperativelyCreatedInjector)).toThrowError();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should instantiate directives that depend on imperatively created injector bindings (root injector)", () => {
|
it("should instantiate directives that depend on imperatively created injector bindings (root injector)", () => {
|
||||||
var imperativelyCreatedInjector = Injector.resolveAndCreate([
|
var imperativelyCreatedInjector = Injector.resolveAndCreate([
|
||||||
bind("service").toValue('appService')
|
bind("service").toValue('appService')
|
||||||
]);
|
]);
|
||||||
var inj = hostShadowInjectors([SimpleDirective], [NeedsService, NeedsAncestorService], imperativelyCreatedInjector);
|
var inj = hostShadowInjectors([SimpleDirective], [NeedsService, NeedsServiceFromHost], imperativelyCreatedInjector);
|
||||||
expect(inj.get(NeedsService).service).toEqual('appService');
|
expect(inj.get(NeedsService).service).toEqual('appService');
|
||||||
expect(inj.get(NeedsAncestorService).service).toEqual('appService');
|
expect(inj.get(NeedsServiceFromHost).service).toEqual('appService');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should instantiate directives that depend on imperatively created injector bindings (child injector)", () => {
|
it("should instantiate directives that depend on imperatively created injector bindings (child injector)", () => {
|
||||||
var imperativelyCreatedInjector = Injector.resolveAndCreate([
|
var imperativelyCreatedInjector = Injector.resolveAndCreate([
|
||||||
bind("service").toValue('appService')
|
bind("service").toValue('appService')
|
||||||
]);
|
]);
|
||||||
var inj = parentChildInjectors([], [NeedsService, NeedsAncestorService], null, imperativelyCreatedInjector);
|
var inj = parentChildInjectors([], [NeedsService, NeedsServiceFromHost], null, imperativelyCreatedInjector);
|
||||||
expect(inj.get(NeedsService).service).toEqual('appService');
|
expect(inj.get(NeedsService).service).toEqual('appService');
|
||||||
expect(inj.get(NeedsAncestorService).service).toEqual('appService');
|
expect(inj.get(NeedsServiceFromHost).service).toEqual('appService');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should prioritize viewInjector over hostInjector for the same binding", () => {
|
it("should prioritize viewInjector over hostInjector for the same binding", () => {
|
||||||
|
@ -750,7 +750,7 @@ export function main() {
|
||||||
hostInjector: [bind('service').toValue('hostService')]})
|
hostInjector: [bind('service').toValue('hostService')]})
|
||||||
)], extraBindings),
|
)], extraBindings),
|
||||||
|
|
||||||
ListWrapper.concat([NeedsAncestorService], extraBindings)
|
ListWrapper.concat([NeedsServiceFromHost], extraBindings)
|
||||||
);
|
);
|
||||||
}).toThrowError(new RegExp("No provider for service!"));
|
}).toThrowError(new RegExp("No provider for service!"));
|
||||||
});
|
});
|
||||||
|
@ -763,31 +763,31 @@ export function main() {
|
||||||
expect(inj.get(NeedsTemplateRef).templateRef).toEqual(templateRef);
|
expect(inj.get(NeedsTemplateRef).templateRef).toEqual(templateRef);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should get directives from ancestor", () => {
|
it("should get directives", () => {
|
||||||
var child = parentChildInjectors(ListWrapper.concat([SimpleDirective], extraBindings),
|
var child = hostShadowInjectors(
|
||||||
[NeedsDirectiveFromAncestor]);
|
ListWrapper.concat([SomeOtherDirective, SimpleDirective], extraBindings),
|
||||||
|
[NeedsDirectiveFromHostShadowDom]);
|
||||||
|
|
||||||
var d = child.get(NeedsDirectiveFromAncestor);
|
var d = child.get(NeedsDirectiveFromHostShadowDom);
|
||||||
|
|
||||||
expect(d).toBeAnInstanceOf(NeedsDirectiveFromAncestor);
|
expect(d).toBeAnInstanceOf(NeedsDirectiveFromHostShadowDom);
|
||||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should get directives crossing the boundaries", () => {
|
it("should get directives from the host", () => {
|
||||||
var child = hostShadowInjectors(
|
var child = parentChildInjectors(ListWrapper.concat([SimpleDirective], extraBindings),
|
||||||
ListWrapper.concat([SomeOtherDirective, SimpleDirective], extraBindings),
|
[NeeedsDirectiveFromHost]);
|
||||||
[NeedsDirectiveFromAnAncestorShadowDom]);
|
|
||||||
|
|
||||||
var d = child.get(NeedsDirectiveFromAnAncestorShadowDom);
|
var d = child.get(NeeedsDirectiveFromHost);
|
||||||
|
|
||||||
expect(d).toBeAnInstanceOf(NeedsDirectiveFromAnAncestorShadowDom);
|
expect(d).toBeAnInstanceOf(NeeedsDirectiveFromHost);
|
||||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should throw when a dependency cannot be resolved", () => {
|
it("should throw when a dependency cannot be resolved", () => {
|
||||||
expect(() => injector(ListWrapper.concat([NeedsDirectiveFromAncestor], extraBindings)))
|
expect(() => injector(ListWrapper.concat([NeeedsDirectiveFromHost], extraBindings)))
|
||||||
.toThrowError(containsRegexp(
|
.toThrowError(containsRegexp(
|
||||||
`No provider for ${stringify(SimpleDirective) }! (${stringify(NeedsDirectiveFromAncestor) } -> ${stringify(SimpleDirective) })`));
|
`No provider for ${stringify(SimpleDirective) }! (${stringify(NeeedsDirectiveFromHost) } -> ${stringify(SimpleDirective) })`));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should inject null when an optional dependency cannot be resolved", () => {
|
it("should inject null when an optional dependency cannot be resolved", () => {
|
||||||
|
@ -820,10 +820,10 @@ export function main() {
|
||||||
var directiveBinding =
|
var directiveBinding =
|
||||||
DirectiveBinding.createFromType(SimpleDirective, new dirAnn.Component());
|
DirectiveBinding.createFromType(SimpleDirective, new dirAnn.Component());
|
||||||
var shadow = hostShadowInjectors(ListWrapper.concat([directiveBinding], extraBindings),
|
var shadow = hostShadowInjectors(ListWrapper.concat([directiveBinding], extraBindings),
|
||||||
[NeedsDirectiveFromAncestor]);
|
[NeeedsDirectiveFromHost]);
|
||||||
|
|
||||||
var d = shadow.get(NeedsDirectiveFromAncestor);
|
var d = shadow.get(NeeedsDirectiveFromHost);
|
||||||
expect(d).toBeAnInstanceOf(NeedsDirectiveFromAncestor);
|
expect(d).toBeAnInstanceOf(NeeedsDirectiveFromHost);
|
||||||
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -44,9 +44,9 @@ import {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
OpaqueToken,
|
OpaqueToken,
|
||||||
Inject,
|
Inject,
|
||||||
Ancestor,
|
Host,
|
||||||
Unbounded,
|
SkipSelf,
|
||||||
UnboundedMetadata
|
SkipSelfMetadata
|
||||||
} from 'angular2/di';
|
} from 'angular2/di';
|
||||||
import {
|
import {
|
||||||
PipeFactory,
|
PipeFactory,
|
||||||
|
@ -435,8 +435,8 @@ export function main() {
|
||||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||||
tcb.overrideView(MyComp, new viewAnn.View({
|
tcb.overrideView(MyComp, new viewAnn.View({
|
||||||
template:
|
template:
|
||||||
'<some-directive><toolbar><template toolbarpart var-toolbar-prop="toolbarProp">{{ctxProp}},{{toolbarProp}},<cmp-with-ancestor></cmp-with-ancestor></template></toolbar></some-directive>',
|
'<some-directive><toolbar><template toolbarpart var-toolbar-prop="toolbarProp">{{ctxProp}},{{toolbarProp}},<cmp-with-host></cmp-with-host></template></toolbar></some-directive>',
|
||||||
directives: [SomeDirective, CompWithAncestor, ToolbarComponent, ToolbarPart]
|
directives: [SomeDirective, CompWithHost, ToolbarComponent, ToolbarPart]
|
||||||
}))
|
}))
|
||||||
.createAsync(MyComp)
|
.createAsync(MyComp)
|
||||||
.then((rootTC) => {
|
.then((rootTC) => {
|
||||||
|
@ -445,7 +445,7 @@ export function main() {
|
||||||
|
|
||||||
expect(rootTC.nativeElement)
|
expect(rootTC.nativeElement)
|
||||||
.toHaveText(
|
.toHaveText(
|
||||||
'TOOLBAR(From myComp,From toolbar,Component with an injected ancestor)');
|
'TOOLBAR(From myComp,From toolbar,Component with an injected host)');
|
||||||
|
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -675,38 +675,38 @@ export function main() {
|
||||||
})}));
|
})}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a component that injects an @Ancestor',
|
it('should create a component that injects an @Host',
|
||||||
inject([TestComponentBuilder, AsyncTestCompleter],
|
inject([TestComponentBuilder, AsyncTestCompleter],
|
||||||
(tcb: TestComponentBuilder, async) => {
|
(tcb: TestComponentBuilder, async) => {
|
||||||
tcb.overrideView(MyComp, new viewAnn.View({
|
tcb.overrideView(MyComp, new viewAnn.View({
|
||||||
template: `
|
template: `
|
||||||
<some-directive>
|
<some-directive>
|
||||||
<p>
|
<p>
|
||||||
<cmp-with-ancestor #child></cmp-with-ancestor>
|
<cmp-with-host #child></cmp-with-host>
|
||||||
</p>
|
</p>
|
||||||
</some-directive>`,
|
</some-directive>`,
|
||||||
directives: [SomeDirective, CompWithAncestor]
|
directives: [SomeDirective, CompWithHost]
|
||||||
}))
|
}))
|
||||||
|
|
||||||
.createAsync(MyComp)
|
.createAsync(MyComp)
|
||||||
.then((rootTC) => {
|
.then((rootTC) => {
|
||||||
|
|
||||||
var childComponent = rootTC.componentViewChildren[0].getLocal('child');
|
var childComponent = rootTC.componentViewChildren[0].getLocal('child');
|
||||||
expect(childComponent.myAncestor).toBeAnInstanceOf(SomeDirective);
|
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
|
||||||
|
|
||||||
async.done();
|
async.done();
|
||||||
})}));
|
})}));
|
||||||
|
|
||||||
it('should create a component that injects an @Ancestor through viewcontainer directive',
|
it('should create a component that injects an @Host through viewcontainer directive',
|
||||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||||
tcb.overrideView(MyComp, new viewAnn.View({
|
tcb.overrideView(MyComp, new viewAnn.View({
|
||||||
template: `
|
template: `
|
||||||
<some-directive>
|
<some-directive>
|
||||||
<p *ng-if="true">
|
<p *ng-if="true">
|
||||||
<cmp-with-ancestor #child></cmp-with-ancestor>
|
<cmp-with-host #child></cmp-with-host>
|
||||||
</p>
|
</p>
|
||||||
</some-directive>`,
|
</some-directive>`,
|
||||||
directives: [SomeDirective, CompWithAncestor, NgIf]
|
directives: [SomeDirective, CompWithHost, NgIf]
|
||||||
}))
|
}))
|
||||||
|
|
||||||
.createAsync(MyComp)
|
.createAsync(MyComp)
|
||||||
|
@ -716,7 +716,7 @@ export function main() {
|
||||||
var tc = rootTC.componentViewChildren[0].children[1];
|
var tc = rootTC.componentViewChildren[0].children[1];
|
||||||
|
|
||||||
var childComponent = tc.getLocal('child');
|
var childComponent = tc.getLocal('child');
|
||||||
expect(childComponent.myAncestor).toBeAnInstanceOf(SomeDirective);
|
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
|
||||||
|
|
||||||
async.done();
|
async.done();
|
||||||
});
|
});
|
||||||
|
@ -1607,12 +1607,12 @@ class SomeDirective {
|
||||||
|
|
||||||
class SomeDirectiveMissingAnnotation {}
|
class SomeDirectiveMissingAnnotation {}
|
||||||
|
|
||||||
@Component({selector: 'cmp-with-ancestor'})
|
@Component({selector: 'cmp-with-host'})
|
||||||
@View({template: '<p>Component with an injected ancestor</p>', directives: [SomeDirective]})
|
@View({template: '<p>Component with an injected host</p>', directives: [SomeDirective]})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class CompWithAncestor {
|
class CompWithHost {
|
||||||
myAncestor: SomeDirective;
|
myHost: SomeDirective;
|
||||||
constructor(@Ancestor() someComp: SomeDirective) { this.myAncestor = someComp; }
|
constructor(@Host() someComp: SomeDirective) { this.myHost = someComp; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: '[child-cmp2]', viewInjector: [MyService]})
|
@Component({selector: '[child-cmp2]', viewInjector: [MyService]})
|
||||||
|
@ -1775,7 +1775,7 @@ class PrivateImpl extends PublicApi {
|
||||||
@Directive({selector: '[needs-public-api]'})
|
@Directive({selector: '[needs-public-api]'})
|
||||||
@Injectable()
|
@Injectable()
|
||||||
class NeedsPublicApi {
|
class NeedsPublicApi {
|
||||||
constructor(@Ancestor() api: PublicApi) { expect(api instanceof PrivateImpl).toBe(true); }
|
constructor(@Host() api: PublicApi) { expect(api instanceof PrivateImpl).toBe(true); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive({selector: '[toolbarpart]'})
|
@Directive({selector: '[toolbarpart]'})
|
||||||
|
@ -1873,7 +1873,7 @@ class DirectiveProvidingInjectableInHostAndView {
|
||||||
class DirectiveConsumingInjectable {
|
class DirectiveConsumingInjectable {
|
||||||
injectable;
|
injectable;
|
||||||
|
|
||||||
constructor(@Ancestor() @Inject(InjectableService) injectable) { this.injectable = injectable; }
|
constructor(@Host() @Inject(InjectableService) injectable) { this.injectable = injectable; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1890,8 +1890,8 @@ class DirectiveContainingDirectiveConsumingAnInjectable {
|
||||||
class DirectiveConsumingInjectableUnbounded {
|
class DirectiveConsumingInjectableUnbounded {
|
||||||
injectable;
|
injectable;
|
||||||
|
|
||||||
constructor(@Unbounded() injectable: InjectableService,
|
constructor(injectable: InjectableService,
|
||||||
@Ancestor() parent: DirectiveContainingDirectiveConsumingAnInjectable) {
|
@SkipSelf() parent: DirectiveContainingDirectiveConsumingAnInjectable) {
|
||||||
this.injectable = injectable;
|
this.injectable = injectable;
|
||||||
parent.directive = this;
|
parent.directive = this;
|
||||||
}
|
}
|
||||||
|
@ -1927,7 +1927,7 @@ function createParentBus(peb) {
|
||||||
selector: 'parent-providing-event-bus',
|
selector: 'parent-providing-event-bus',
|
||||||
hostInjector: [
|
hostInjector: [
|
||||||
new Binding(EventBus,
|
new Binding(EventBus,
|
||||||
{toFactory: createParentBus, deps: [[EventBus, new UnboundedMetadata()]]})
|
{toFactory: createParentBus, deps: [[EventBus, new SkipSelfMetadata()]]})
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
@View({
|
@View({
|
||||||
|
@ -1940,7 +1940,7 @@ class ParentProvidingEventBus {
|
||||||
bus: EventBus;
|
bus: EventBus;
|
||||||
grandParentBus: EventBus;
|
grandParentBus: EventBus;
|
||||||
|
|
||||||
constructor(bus: EventBus, @Unbounded() grandParentBus: EventBus) {
|
constructor(bus: EventBus, @SkipSelf() grandParentBus: EventBus) {
|
||||||
this.bus = bus;
|
this.bus = bus;
|
||||||
this.grandParentBus = grandParentBus;
|
this.grandParentBus = grandParentBus;
|
||||||
}
|
}
|
||||||
|
@ -1950,7 +1950,7 @@ class ParentProvidingEventBus {
|
||||||
class ChildConsumingEventBus {
|
class ChildConsumingEventBus {
|
||||||
bus: EventBus;
|
bus: EventBus;
|
||||||
|
|
||||||
constructor(@Unbounded() bus: EventBus) { this.bus = bus; }
|
constructor(@SkipSelf() bus: EventBus) { this.bus = bus; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive({selector: '[some-impvp]', properties: ['someImpvp']})
|
@Directive({selector: '[some-impvp]', properties: ['someImpvp']})
|
||||||
|
|
|
@ -19,8 +19,8 @@ import {
|
||||||
Injectable,
|
Injectable,
|
||||||
InjectMetadata,
|
InjectMetadata,
|
||||||
SelfMetadata,
|
SelfMetadata,
|
||||||
AncestorMetadata,
|
HostMetadata,
|
||||||
UnboundedMetadata,
|
SkipSelfMetadata,
|
||||||
Optional,
|
Optional,
|
||||||
Inject,
|
Inject,
|
||||||
BindingWithVisibility,
|
BindingWithVisibility,
|
||||||
|
@ -420,57 +420,56 @@ export function main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("@Ancestor()", () => {
|
describe("@Host()", () => {
|
||||||
it("should return a dependency from same boundary", () => {
|
it("should return a dependency from same host", () => {
|
||||||
var parent = Injector.resolveAndCreate([Engine]);
|
var parent = Injector.resolveAndCreate([Engine]);
|
||||||
var child = parent.resolveAndCreateChild(
|
var child = parent.resolveAndCreateChild(
|
||||||
[bind(Car).toFactory((e) => new Car(e), [[Engine, new AncestorMetadata()]])]);
|
[bind(Car).toFactory((e) => new Car(e), [[Engine, new HostMetadata()]])]);
|
||||||
|
|
||||||
expect(child.get(Car)).toBeAnInstanceOf(Car);
|
expect(child.get(Car)).toBeAnInstanceOf(Car);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return a private dependency declared at the boundary", () => {
|
it("should return a private dependency declared at the host", () => {
|
||||||
var engine = Injector.resolve([Engine])[0];
|
var engine = Injector.resolve([Engine])[0];
|
||||||
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PRIVATE)]);
|
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PRIVATE)]);
|
||||||
var parent = new Injector(protoParent);
|
var parent = new Injector(protoParent);
|
||||||
|
|
||||||
var child = Injector.resolveAndCreate(
|
var child = Injector.resolveAndCreate(
|
||||||
[bind(Car).toFactory((e) => new Car(e), [[Engine, new AncestorMetadata()]])]);
|
[bind(Car).toFactory((e) => new Car(e), [[Engine, new HostMetadata()]])]);
|
||||||
|
|
||||||
child.internalStrategy.attach(parent, true); // boundary
|
child.internalStrategy.attach(parent, true); // host
|
||||||
|
|
||||||
expect(child.get(Car)).toBeAnInstanceOf(Car);
|
expect(child.get(Car)).toBeAnInstanceOf(Car);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not return a public dependency declared at the boundary", () => {
|
it("should not return a public dependency declared at the host", () => {
|
||||||
var engine = Injector.resolve([Engine])[0];
|
var engine = Injector.resolve([Engine])[0];
|
||||||
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PUBLIC)]);
|
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PUBLIC)]);
|
||||||
var parent = new Injector(protoParent);
|
var parent = new Injector(protoParent);
|
||||||
|
|
||||||
var child = Injector.resolveAndCreate(
|
var child = Injector.resolveAndCreate(
|
||||||
[bind(Car).toFactory((e) => new Car(e), [[Engine, new AncestorMetadata()]])]);
|
[bind(Car).toFactory((e) => new Car(e), [[Engine, new HostMetadata()]])]);
|
||||||
|
|
||||||
child.internalStrategy.attach(parent, true); // boundary
|
child.internalStrategy.attach(parent, true); // host
|
||||||
|
|
||||||
expect(() => child.get(Car))
|
expect(() => child.get(Car))
|
||||||
.toThrowError(`No provider for Engine! (${stringify(Car)} -> ${stringify(Engine)})`);
|
.toThrowError(`No provider for Engine! (${stringify(Car)} -> ${stringify(Engine)})`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return a dependency from self when explicitly specified", () => {
|
it("should not skip self", () => {
|
||||||
var parent = Injector.resolveAndCreate([Engine]);
|
var parent = Injector.resolveAndCreate([Engine]);
|
||||||
var child = parent.resolveAndCreateChild([
|
var child = parent.resolveAndCreateChild([
|
||||||
bind(Engine)
|
bind(Engine)
|
||||||
.toClass(TurboEngine),
|
.toClass(TurboEngine),
|
||||||
bind(Car)
|
bind(Car).toFactory((e) => new Car(e), [[Engine, new HostMetadata()]])
|
||||||
.toFactory((e) => new Car(e), [[Engine, new AncestorMetadata({self: true})]])
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(child.get(Car).engine).toBeAnInstanceOf(TurboEngine);
|
expect(child.get(Car).engine).toBeAnInstanceOf(TurboEngine);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("@Unboudned()", () => {
|
describe("default", () => {
|
||||||
it("should return a private dependency declared at the boundary", () => {
|
it("should return a private dependency declared at the host", () => {
|
||||||
var engine = Injector.resolve([Engine])[0];
|
var engine = Injector.resolve([Engine])[0];
|
||||||
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PRIVATE)]);
|
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PRIVATE)]);
|
||||||
var parent = new Injector(protoParent);
|
var parent = new Injector(protoParent);
|
||||||
|
@ -478,14 +477,14 @@ export function main() {
|
||||||
var child = Injector.resolveAndCreate([
|
var child = Injector.resolveAndCreate([
|
||||||
bind(Engine)
|
bind(Engine)
|
||||||
.toClass(BrokenEngine),
|
.toClass(BrokenEngine),
|
||||||
bind(Car).toFactory((e) => new Car(e), [[Engine, new UnboundedMetadata()]])
|
bind(Car).toFactory((e) => new Car(e), [[Engine, new SkipSelfMetadata()]])
|
||||||
]);
|
]);
|
||||||
child.internalStrategy.attach(parent, true); // boundary
|
child.internalStrategy.attach(parent, true); // boundary
|
||||||
|
|
||||||
expect(child.get(Car)).toBeAnInstanceOf(Car);
|
expect(child.get(Car)).toBeAnInstanceOf(Car);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return a public dependency declared at the boundary", () => {
|
it("should return a public dependency declared at the host", () => {
|
||||||
var engine = Injector.resolve([Engine])[0];
|
var engine = Injector.resolve([Engine])[0];
|
||||||
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PUBLIC)]);
|
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PUBLIC)]);
|
||||||
var parent = new Injector(protoParent);
|
var parent = new Injector(protoParent);
|
||||||
|
@ -493,14 +492,14 @@ export function main() {
|
||||||
var child = Injector.resolveAndCreate([
|
var child = Injector.resolveAndCreate([
|
||||||
bind(Engine)
|
bind(Engine)
|
||||||
.toClass(BrokenEngine),
|
.toClass(BrokenEngine),
|
||||||
bind(Car).toFactory((e) => new Car(e), [[Engine, new UnboundedMetadata()]])
|
bind(Car).toFactory((e) => new Car(e), [[Engine, new SkipSelfMetadata()]])
|
||||||
]);
|
]);
|
||||||
child.internalStrategy.attach(parent, true); // boundary
|
child.internalStrategy.attach(parent, true); // boundary
|
||||||
|
|
||||||
expect(child.get(Car)).toBeAnInstanceOf(Car);
|
expect(child.get(Car)).toBeAnInstanceOf(Car);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not return a private dependency declared NOT at the boundary", () => {
|
it("should not return a private dependency declared NOT at the host", () => {
|
||||||
var engine = Injector.resolve([Engine])[0];
|
var engine = Injector.resolve([Engine])[0];
|
||||||
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PRIVATE)]);
|
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PRIVATE)]);
|
||||||
var parent = new Injector(protoParent);
|
var parent = new Injector(protoParent);
|
||||||
|
@ -508,7 +507,7 @@ export function main() {
|
||||||
var child = Injector.resolveAndCreate([
|
var child = Injector.resolveAndCreate([
|
||||||
bind(Engine)
|
bind(Engine)
|
||||||
.toClass(BrokenEngine),
|
.toClass(BrokenEngine),
|
||||||
bind(Car).toFactory((e) => new Car(e), [[Engine, new UnboundedMetadata()]])
|
bind(Car).toFactory((e) => new Car(e), [[Engine, new SkipSelfMetadata()]])
|
||||||
]);
|
]);
|
||||||
child.internalStrategy.attach(parent, false);
|
child.internalStrategy.attach(parent, false);
|
||||||
|
|
||||||
|
@ -516,13 +515,12 @@ export function main() {
|
||||||
.toThrowError(`No provider for Engine! (${stringify(Car)} -> ${stringify(Engine)})`);
|
.toThrowError(`No provider for Engine! (${stringify(Car)} -> ${stringify(Engine)})`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return a dependency from self when explicitly specified", () => {
|
it("should not skip self", () => {
|
||||||
var parent = Injector.resolveAndCreate([Engine]);
|
var parent = Injector.resolveAndCreate([Engine]);
|
||||||
var child = parent.resolveAndCreateChild([
|
var child = parent.resolveAndCreateChild([
|
||||||
bind(Engine)
|
bind(Engine)
|
||||||
.toClass(TurboEngine),
|
.toClass(TurboEngine),
|
||||||
bind(Car)
|
bind(Car).toFactory((e) => new Car(e), [Engine])
|
||||||
.toFactory((e) => new Car(e), [[Engine, new UnboundedMetadata({self: true})]])
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(child.get(Car).engine).toBeAnInstanceOf(TurboEngine);
|
expect(child.get(Car).engine).toBeAnInstanceOf(TurboEngine);
|
||||||
|
|
|
@ -3,7 +3,8 @@ import {
|
||||||
Directive,
|
Directive,
|
||||||
View,
|
View,
|
||||||
ViewEncapsulation,
|
ViewEncapsulation,
|
||||||
Ancestor,
|
Host,
|
||||||
|
SkipSelf,
|
||||||
ElementRef,
|
ElementRef,
|
||||||
DynamicComponentLoader,
|
DynamicComponentLoader,
|
||||||
ComponentRef,
|
ComponentRef,
|
||||||
|
@ -212,8 +213,7 @@ export class MdDialogConfig {
|
||||||
})
|
})
|
||||||
@View({
|
@View({
|
||||||
templateUrl: 'package:angular2_material/src/components/dialog/dialog.html',
|
templateUrl: 'package:angular2_material/src/components/dialog/dialog.html',
|
||||||
directives: [forwardRef(() => MdDialogContent)],
|
directives: [forwardRef(() => MdDialogContent)]
|
||||||
encapsulation: ViewEncapsulation.NONE
|
|
||||||
})
|
})
|
||||||
class MdDialogContainer {
|
class MdDialogContainer {
|
||||||
// Ref to the dialog content. Used by the DynamicComponentLoader to load the dialog content.
|
// Ref to the dialog content. Used by the DynamicComponentLoader to load the dialog content.
|
||||||
|
@ -245,7 +245,7 @@ class MdDialogContainer {
|
||||||
*/
|
*/
|
||||||
@Directive({selector: 'md-dialog-content'})
|
@Directive({selector: 'md-dialog-content'})
|
||||||
class MdDialogContent {
|
class MdDialogContent {
|
||||||
constructor(@Ancestor() dialogContainer: MdDialogContainer, elementRef: ElementRef) {
|
constructor(@Host() @SkipSelf() dialogContainer: MdDialogContainer, elementRef: ElementRef) {
|
||||||
dialogContainer.contentRef = elementRef;
|
dialogContainer.contentRef = elementRef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
import {Component, View, ViewEncapsulation, Ancestor, LifecycleEvent} from 'angular2/angular2';
|
import {
|
||||||
|
Component,
|
||||||
|
View,
|
||||||
|
ViewEncapsulation,
|
||||||
|
Host,
|
||||||
|
SkipSelf,
|
||||||
|
LifecycleEvent
|
||||||
|
} from 'angular2/angular2';
|
||||||
|
|
||||||
import {ListWrapper} from 'angular2/src/facade/collection';
|
import {ListWrapper} from 'angular2/src/facade/collection';
|
||||||
import {StringWrapper, isPresent, isString, NumberWrapper} from 'angular2/src/facade/lang';
|
import {StringWrapper, isPresent, isString, NumberWrapper} from 'angular2/src/facade/lang';
|
||||||
|
@ -244,7 +251,7 @@ export class MdGridTile {
|
||||||
|
|
||||||
isRegisteredWithGridList: boolean;
|
isRegisteredWithGridList: boolean;
|
||||||
|
|
||||||
constructor(@Ancestor() gridList: MdGridList) {
|
constructor(@SkipSelf() @Host() gridList: MdGridList) {
|
||||||
this.gridList = gridList;
|
this.gridList = gridList;
|
||||||
|
|
||||||
// Tiles default to 1x1, but rowspan and colspan can be changed via binding.
|
// Tiles default to 1x1, but rowspan and colspan can be changed via binding.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {Directive, LifecycleEvent, Attribute, Ancestor} from 'angular2/angular2';
|
import {Directive, LifecycleEvent, Attribute, Host, SkipSelf} from 'angular2/angular2';
|
||||||
|
|
||||||
import {ObservableWrapper, EventEmitter} from 'angular2/src/facade/async';
|
import {ObservableWrapper, EventEmitter} from 'angular2/src/facade/async';
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ export class MdInput {
|
||||||
mdChange: EventEmitter;
|
mdChange: EventEmitter;
|
||||||
mdFocusChange: EventEmitter;
|
mdFocusChange: EventEmitter;
|
||||||
|
|
||||||
constructor(@Attribute('value') value: string, @Ancestor() container: MdInputContainer,
|
constructor(@Attribute('value') value: string, @SkipSelf() @Host() container: MdInputContainer,
|
||||||
@Attribute('id') id: string) {
|
@Attribute('id') id: string) {
|
||||||
// TODO(jelbourn): Remove this when #1402 is done.
|
// TODO(jelbourn): Remove this when #1402 is done.
|
||||||
this.yes = true;
|
this.yes = true;
|
||||||
|
@ -111,7 +111,7 @@ export class MdInput {
|
||||||
export class MdTextarea extends MdInput {
|
export class MdTextarea extends MdInput {
|
||||||
constructor(
|
constructor(
|
||||||
@Attribute('value') value: string,
|
@Attribute('value') value: string,
|
||||||
@Ancestor() container: MdInputContainer,
|
@SkipSelf() @Host() container: MdInputContainer,
|
||||||
@Attribute('id') id: string) {
|
@Attribute('id') id: string) {
|
||||||
super(value, container, id);
|
super(value, container, id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@ import {
|
||||||
View,
|
View,
|
||||||
ViewEncapsulation,
|
ViewEncapsulation,
|
||||||
LifecycleEvent,
|
LifecycleEvent,
|
||||||
Ancestor,
|
Host,
|
||||||
|
SkipSelf,
|
||||||
Attribute,
|
Attribute,
|
||||||
Optional
|
Optional
|
||||||
} from 'angular2/angular2';
|
} from 'angular2/angular2';
|
||||||
|
@ -232,7 +233,7 @@ export class MdRadioButton {
|
||||||
|
|
||||||
role: string;
|
role: string;
|
||||||
|
|
||||||
constructor(@Optional() @Ancestor() radioGroup: MdRadioGroup, @Attribute('id') id: string,
|
constructor(@Optional() @SkipSelf() @Host() radioGroup: MdRadioGroup, @Attribute('id') id: string,
|
||||||
@Attribute('tabindex') tabindex: string, radioDispatcher: MdRadioDispatcher) {
|
@Attribute('tabindex') tabindex: string, radioDispatcher: MdRadioDispatcher) {
|
||||||
// Assertions. Ideally these should be stripped out by the compiler.
|
// Assertions. Ideally these should be stripped out by the compiler.
|
||||||
// TODO(jelbourn): Assert that there's no name binding AND a parent radio group.
|
// TODO(jelbourn): Assert that there's no name binding AND a parent radio group.
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
Component,
|
Component,
|
||||||
Directive,
|
Directive,
|
||||||
View,
|
View,
|
||||||
Ancestor
|
Host
|
||||||
} from 'angular2/bootstrap';
|
} from 'angular2/bootstrap';
|
||||||
import {formDirectives, NgControl, Validators, NgFormModel, FormBuilder} from 'angular2/forms';
|
import {formDirectives, NgControl, Validators, NgFormModel, FormBuilder} from 'angular2/forms';
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class ShowError {
|
||||||
controlPath: string;
|
controlPath: string;
|
||||||
errorTypes: List<string>;
|
errorTypes: List<string>;
|
||||||
|
|
||||||
constructor(@Ancestor() formDir: NgFormModel) { this.formDir = formDir; }
|
constructor(@Host() formDir: NgFormModel) { this.formDir = formDir; }
|
||||||
|
|
||||||
get errorMessage() {
|
get errorMessage() {
|
||||||
var c = this.formDir.form.find(this.controlPath);
|
var c = this.formDir.form.find(this.controlPath);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
Component,
|
Component,
|
||||||
Directive,
|
Directive,
|
||||||
View,
|
View,
|
||||||
Ancestor,
|
Host,
|
||||||
NgValidator,
|
NgValidator,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
Binding,
|
Binding,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
Component,
|
Component,
|
||||||
Directive,
|
Directive,
|
||||||
View,
|
View,
|
||||||
Ancestor,
|
Host,
|
||||||
NgValidator,
|
NgValidator,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
Binding
|
Binding
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
Component,
|
Component,
|
||||||
Directive,
|
Directive,
|
||||||
View,
|
View,
|
||||||
Ancestor,
|
Host,
|
||||||
NgValidator,
|
NgValidator,
|
||||||
forwardRef,
|
forwardRef,
|
||||||
Binding
|
Binding
|
||||||
|
@ -76,7 +76,7 @@ class ShowError {
|
||||||
controlPath: string;
|
controlPath: string;
|
||||||
errorTypes: List<string>;
|
errorTypes: List<string>;
|
||||||
|
|
||||||
constructor(@Ancestor() formDir: NgForm) { this.formDir = formDir; }
|
constructor(@Host() formDir: NgForm) { this.formDir = formDir; }
|
||||||
|
|
||||||
get errorMessage() {
|
get errorMessage() {
|
||||||
var c = this.formDir.form.find(this.controlPath);
|
var c = this.formDir.form.find(this.controlPath);
|
||||||
|
|
Loading…
Reference in New Issue