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:
vsavkin 2015-07-29 11:26:09 -07:00
parent a9ec6b9064
commit 985627bd65
27 changed files with 246 additions and 268 deletions

View File

@ -5,7 +5,7 @@
* Annotations provide the additional information that Angular requires in order to run your
* application. This module
* 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.
*
*/

View File

@ -8,12 +8,10 @@ export {
InjectMetadata,
OptionalMetadata,
InjectableMetadata,
VisibilityMetadata,
SelfMetadata,
AncestorMetadata,
UnboundedMetadata,
DependencyMetadata,
DEFAULT_VISIBILITY
HostMetadata,
SkipSelfMetadata,
DependencyMetadata
} from './src/di/metadata';
// we have to reexport * because Dart and TS export two different sets of types

View File

@ -261,7 +261,7 @@ Injecting other directives into directives follows a similar mechanism as inject
There are five kinds of visibilities:
* (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`)
* `@descendant`: Inject a list of any children which match a given type. (Used with `Query`)
@ -299,8 +299,8 @@ class FieldSet { |
@Directive({ selector: 'field' }) |
class Field { |
constructor( |
@ancestor field:Form, |
@ancestor field:FieldSet, |
@SkipSelf() field:Form, |
@SkipSelf() field:FieldSet, |
) { ... } |
} |
|
@ -336,7 +336,7 @@ Shadow DOM provides an encapsulation for components, so as a general rule it doe
})
class Kid {
constructor(
@Ancestor() dad:Dad,
@SkipSelf() dad:Dad,
@Optional() grandpa:Grandpa
) {
this.name = 'Billy';
@ -353,7 +353,7 @@ class Kid {
directives: [Kid]
})
class Dad {
constructor(@Ancestor() dad:Grandpa) {
constructor(@SkipSelf() dad:Grandpa) {
this.name = 'Joe Jr';
this.dad = dad.name;
}

View File

@ -1,7 +1,7 @@
import {ListWrapper, isListLikeIterable, StringMapWrapper} from 'angular2/src/facade/collection';
import {isBlank, isPresent, BaseException, CONST} from 'angular2/src/facade/lang';
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 {Binding} from 'angular2/di';
@ -80,7 +80,7 @@ export class Pipes {
return Pipes.create(config, pipes);
},
// 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()]]
});
}

View File

@ -53,11 +53,9 @@ import {DEFAULT} from 'angular2/change_detection';
*
* To inject other directives, declare the constructor parameter as:
* - `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
* Shadow DOM root. Current element is not included in the resolution, therefore even if it could
* resolve it, it will
* be ignored.
* Shadow DOM root.
* - `@Query(DirectiveType) query:QueryList<DirectiveType>`: A live collection of direct child
* directives.
* - `@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
*
* Directives can inject other directives declared on any ancestor element (in the current Shadow
* DOM), i.e. on the
* parent element and its parents. By definition, a directive with an `@Ancestor` annotation does
* not attempt to
* resolve dependencies for the current element, even if this would satisfy the dependency.
*
* DOM), i.e. on the current element, the
* parent element, or its parents.
* ```
* @Directive({ selector: '[my-directive]' })
* class MyDirective {
* constructor(@Ancestor() dependency: Dependency) {
* constructor(@Host() dependency: Dependency) {
* 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
* have returned
* `dependency="1"`.

View File

@ -25,7 +25,6 @@ import {
AbstractBindingError,
CyclicDependencyError,
resolveForwardRef,
VisibilityMetadata,
DependencyProvider
} from 'angular2/di';
import {
@ -167,9 +166,10 @@ export class TreeNode<T extends TreeNode<any>> {
}
export class DirectiveDependency extends Dependency {
constructor(key: Key, optional: boolean, visibility: any, properties: List<any>,
public attributeName: string, public queryDecorator: Query) {
super(key, optional, visibility, properties);
constructor(key: Key, optional: boolean, lowerBoundVisibility: Object,
upperBoundVisibility: Object, properties: List<any>, public attributeName: string,
public queryDecorator: Query) {
super(key, optional, lowerBoundVisibility, upperBoundVisibility, properties);
this._verify();
}
@ -183,9 +183,9 @@ export class DirectiveDependency extends Dependency {
}
static createFrom(d: Dependency): Dependency {
return new DirectiveDependency(d.key, d.optional, d.visibility, d.properties,
DirectiveDependency._attributeName(d.properties),
DirectiveDependency._query(d.properties));
return new DirectiveDependency(
d.key, d.optional, d.lowerBoundVisibility, d.upperBoundVisibility, d.properties,
DirectiveDependency._attributeName(d.properties), DirectiveDependency._query(d.properties));
}
static _attributeName(properties): string {

View File

@ -14,9 +14,10 @@ import {Key} from './key';
import {
InjectMetadata,
InjectableMetadata,
VisibilityMetadata,
OptionalMetadata,
DEFAULT_VISIBILITY,
SelfMetadata,
HostMetadata,
SkipSelfMetadata,
DependencyMetadata
} from './metadata';
import {NoAnnotationError} from './exceptions';
@ -26,12 +27,10 @@ import {resolveForwardRef} from './forward_ref';
* @private
*/
export class Dependency {
constructor(public key: Key, public optional: boolean, public visibility: VisibilityMetadata,
public properties: List<any>) {}
constructor(public key: Key, public optional: boolean, public lowerBoundVisibility: any,
public upperBoundVisibility: any, public properties: List<any>) {}
static fromKey(key: Key): Dependency {
return new Dependency(key, false, DEFAULT_VISIBILITY, []);
}
static fromKey(key: Key): Dependency { return new Dependency(key, false, null, null, []); }
}
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));
}
function _extractToken(typeOrFunc, annotations /*List<any> | any*/, params: List<List<any>>):
function _extractToken(typeOrFunc, metadata /*List<any> | any*/, params: List<List<any>>):
Dependency {
var depProps = [];
var token = null;
var optional = false;
if (!isArray(annotations)) {
return _createDependency(annotations, optional, DEFAULT_VISIBILITY, depProps);
if (!isArray(metadata)) {
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) {
var paramAnnotation = annotations[i];
for (var i = 0; i < metadata.length; ++i) {
var paramMetadata = metadata[i];
if (paramAnnotation instanceof Type) {
token = paramAnnotation;
if (paramMetadata instanceof Type) {
token = paramMetadata;
} else if (paramAnnotation instanceof InjectMetadata) {
token = paramAnnotation.token;
} else if (paramMetadata instanceof InjectMetadata) {
token = paramMetadata.token;
} else if (paramAnnotation instanceof OptionalMetadata) {
} else if (paramMetadata instanceof OptionalMetadata) {
optional = true;
} else if (paramAnnotation instanceof VisibilityMetadata) {
visibility = paramAnnotation;
} else if (paramMetadata instanceof SelfMetadata) {
upperBoundVisibility = paramMetadata;
} else if (paramAnnotation instanceof DependencyMetadata) {
if (isPresent(paramAnnotation.token)) {
token = paramAnnotation.token;
} else if (paramMetadata instanceof HostMetadata) {
upperBoundVisibility = paramMetadata;
} 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);
if (isPresent(token)) {
return _createDependency(token, optional, visibility, depProps);
return _createDependency(token, optional, lowerBoundVisibility, upperBoundVisibility, depProps);
} else {
throw new NoAnnotationError(typeOrFunc, params);
}
}
function _createDependency(token, optional, visibility, depProps): Dependency {
return new Dependency(Key.get(token), optional, visibility, depProps);
function _createDependency(token, optional, lowerBoundVisibility, upperBoundVisibility, depProps):
Dependency {
return new Dependency(Key.get(token), optional, lowerBoundVisibility, upperBoundVisibility,
depProps);
}

View File

@ -32,15 +32,15 @@ class Self extends SelfMetadata {
}
/**
* {@link AncestorMetadata}.
* {@link HostMetadata}.
*/
class Ancestor extends AncestorMetadata {
const Ancestor({bool self}) : super(self: self);
class Host extends HostMetadata {
const Host() : super();
}
/**
* {@link UnboundedMetadata}.
* {@link SkipSelfMetadata}.
*/
class Unbounded extends UnboundedMetadata {
const Unbounded({bool self}) : super(self: self);
class SkipSelf extends SkipSelfMetadata {
const SkipSelf() : super();
}

View File

@ -3,9 +3,8 @@ import {
OptionalMetadata,
InjectableMetadata,
SelfMetadata,
VisibilityMetadata,
AncestorMetadata,
UnboundedMetadata
HostMetadata,
SkipSelfMetadata
} from './metadata';
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 {
(visibility?: {self: boolean}): any;
new (visibility?: {self: boolean}): AncestorMetadata;
export interface HostFactory {
(): any;
new (): HostMetadata;
}
/**
* Factory for creating {@link UnboundedMetadata}.
* Factory for creating {@link SkipSelfMetadata}.
*/
export interface UnboundedFactory {
(visibility?: {self: boolean}): any;
new (visibility?: {self: boolean}): UnboundedMetadata;
export interface SkipSelfFactory {
(): any;
new (): SkipSelfMetadata;
}
/**
@ -78,11 +77,11 @@ export var Injectable: InjectableFactory = <InjectableFactory>makeDecorator(Inje
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);

View File

@ -13,7 +13,7 @@ import {
import {FunctionWrapper, Type, isPresent, isBlank, CONST_EXPR} from 'angular2/src/facade/lang';
import {Key} from './key';
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 _notFound = CONST_EXPR(new Object());
@ -192,7 +192,7 @@ export interface InjectorStrategy {
getObjAtIndex(index: number): any;
getMaxNumberOfObjects(): number;
attach(parent: Injector, isBoundary: boolean): void;
attach(parent: Injector, isHost: boolean): void;
resetConstructionCounter(): void;
instantiateBinding(binding: ResolvedBinding, visibility: number): any;
}
@ -217,10 +217,10 @@ export class InjectorInlineStrategy implements InjectorStrategy {
return this.injector._new(binding, visibility);
}
attach(parent: Injector, isBoundary: boolean): void {
attach(parent: Injector, isHost: boolean): void {
var inj = this.injector;
inj._parent = parent;
inj._isBoundary = isBoundary;
inj._isHost = isHost;
}
getObjByKeyId(keyId: number, visibility: number): any {
@ -323,10 +323,10 @@ export class InjectorDynamicStrategy implements InjectorStrategy {
return this.injector._new(binding, visibility);
}
attach(parent: Injector, isBoundary: boolean): void {
attach(parent: Injector, isHost: boolean): void {
var inj = this.injector;
inj._parent = parent;
inj._isBoundary = isBoundary;
inj._isHost = isHost;
}
getObjByKeyId(keyId: number, visibility: number): any {
@ -466,7 +466,7 @@ export class Injector {
}
_strategy: InjectorStrategy;
_isBoundary: boolean = false;
_isHost: boolean = false;
_constructionCounter: number = 0;
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.
*/
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.
*/
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) {
return special;
} 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,
bindingVisibility: number): any {
private _getByKey(key: Key, lowerBoundVisibility: Object, upperBoundVisibility: Object,
optional: boolean, bindingVisibility: number): any {
if (key === INJECTOR_KEY) {
return this;
}
if (depVisibility instanceof SelfMetadata) {
if (upperBoundVisibility instanceof SelfMetadata) {
return this._getByKeySelf(key, optional, bindingVisibility);
} else if (depVisibility instanceof AncestorMetadata) {
return this._getByKeyAncestor(key, optional, bindingVisibility, depVisibility.includeSelf);
} else if (upperBoundVisibility instanceof HostMetadata) {
return this._getByKeyHost(key, optional, bindingVisibility, lowerBoundVisibility);
} 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);
}
_getByKeyAncestor(key: Key, optional: boolean, bindingVisibility: number,
includeSelf: boolean): any {
_getByKeyHost(key: Key, optional: boolean, bindingVisibility: number,
lowerBoundVisibility: Object): any {
var inj = this;
if (!includeSelf) {
if (inj._isBoundary) {
if (lowerBoundVisibility instanceof SkipSelfMetadata) {
if (inj._isHost) {
return this._getPrivateDependency(key, optional, inj);
} else {
inj = inj._parent;
@ -729,7 +730,7 @@ export class Injector {
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
if (obj !== undefinedValue) return obj;
if (isPresent(inj._parent) && inj._isBoundary) {
if (isPresent(inj._parent) && inj._isHost) {
return this._getPrivateDependency(key, optional, inj);
} else {
inj = inj._parent;
@ -744,11 +745,12 @@ export class Injector {
return (obj !== undefinedValue) ? obj : this._throwOrNull(key, optional);
}
_getByKeyUnbounded(key: Key, optional: boolean, bindingVisibility: number,
includeSelf: boolean): any {
_getByKeyDefault(key: Key, optional: boolean, bindingVisibility: number,
lowerBoundVisibility: Object): any {
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;
}
@ -756,7 +758,7 @@ export class Injector {
var obj = inj._strategy.getObjByKeyId(key.id, bindingVisibility);
if (obj !== undefinedValue) return obj;
bindingVisibility = inj._isBoundary ? PUBLIC_AND_PRIVATE : PUBLIC;
bindingVisibility = inj._isHost ? PUBLIC_AND_PRIVATE : PUBLIC;
inj = inj._parent;
}

View File

@ -82,22 +82,6 @@ export class InjectableMetadata {
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.
*
@ -117,50 +101,45 @@ export class VisibilityMetadata {
* ```
*/
@CONST()
export class SelfMetadata extends VisibilityMetadata {
constructor() { super(false, true); }
export class SelfMetadata {
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
*
*
* ```
* class Dependency {
* class Service {}
*
* class ParentService implements Service {
* }
*
* class NeedsDependency {
* constructor(public @Ancestor() dependency:Dependency) {}
* class ChildService implements Service {
* constructor(public @SkipSelf() parentService:Service) {}
* }
*
* var parent = Injector.resolveAndCreate([
* bind(Dependency).toClass(AncestorDependency)
* bind(Service).toClass(ParentService)
* ]);
* var child = parent.resolveAndCreateChild([]);
* var grandChild = child.resolveAndCreateChild([NeedsDependency, Depedency]);
* var nd = grandChild.get(NeedsDependency);
* expect(nd.dependency).toBeAnInstanceOf(AncestorDependency);
* ```
*
* 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) {}
* }
* var child = parent.resolveAndCreateChild([
* bind(Service).toClass(ChildSerice)
* ]);
* var s = child.get(Service);
* expect(s).toBeAnInstanceOf(ChildService);
* expect(s.parentService).toBeAnInstanceOf(ParentService);
* ```
*/
@CONST()
export class AncestorMetadata extends VisibilityMetadata {
constructor({self}: {self?: boolean} = {}) { super(false, self); }
toString(): string { return `@Ancestor(self: ${this.includeSelf}})`; }
export class SkipSelfMetadata {
toString(): string { return `@SkipSelf()`; }
}
/**
* 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
*
@ -169,32 +148,20 @@ export class AncestorMetadata extends VisibilityMetadata {
* }
*
* class NeedsDependency {
* constructor(public @Ancestor() dependency:Dependency) {}
* constructor(public @Host() dependency:Dependency) {}
* }
*
* var parent = Injector.resolveAndCreate([
* bind(Dependency).toClass(AncestorDependency)
* bind(Dependency).toClass(HostDependency)
* ]);
* var child = parent.resolveAndCreateChild([]);
* var grandChild = child.resolveAndCreateChild([NeedsDependency, Depedency]);
* 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()
export class UnboundedMetadata extends VisibilityMetadata {
constructor({self}: {self?: boolean} = {}) { super(true, self); }
toString(): string { return `@Unbounded(self: ${this.includeSelf}})`; }
export class HostMetadata {
toString(): string { return `@Host()`; }
}
export const DEFAULT_VISIBILITY: VisibilityMetadata =
CONST_EXPR(new UnboundedMetadata({self: true}));

View File

@ -1,5 +1,5 @@
import {Directive} from 'angular2/annotations';
import {Ancestor} from 'angular2/di';
import {Host} from 'angular2/di';
import {ViewContainerRef, TemplateRef} from 'angular2/core';
import {isPresent, isBlank, normalizeBlank} from 'angular2/src/facade/lang';
import {ListWrapper, List, MapWrapper, Map} from 'angular2/src/facade/collection';
@ -157,7 +157,7 @@ export class NgSwitchWhen {
_view: SwitchView;
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef,
@Ancestor() sswitch: NgSwitch) {
@Host() sswitch: NgSwitch) {
// `_whenDefault` is used as a marker for a not yet initialized value
this._value = _whenDefault;
this._switch = sswitch;
@ -187,7 +187,7 @@ export class NgSwitchWhen {
@Directive({selector: '[ng-switch-default]'})
export class NgSwitchDefault {
constructor(viewContainer: ViewContainerRef, templateRef: TemplateRef,
@Ancestor() sswitch: NgSwitch) {
@Host() sswitch: NgSwitch) {
sswitch._registerView(_whenDefault, new SwitchView(viewContainer, templateRef));
}
}

View File

@ -1,5 +1,5 @@
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 {CONST_EXPR} from 'angular2/src/facade/lang';
@ -57,7 +57,7 @@ const controlGroupBinding =
})
export class NgControlGroup extends ControlContainer {
_parent: ControlContainer;
constructor(@Ancestor() _parent: ControlContainer) {
constructor(@Host() @SkipSelf() _parent: ControlContainer) {
super();
this._parent = _parent;
}

View File

@ -4,7 +4,7 @@ import {List, StringMap} from 'angular2/src/facade/collection';
import {QueryList} from 'angular2/core';
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 {NgControl} from './ng_control';
@ -88,7 +88,7 @@ export class NgControlName extends NgControl {
_added = false;
// 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>) {
super();
this._parent = parent;

View File

@ -3,7 +3,7 @@ import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
import {QueryList} from 'angular2/core';
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 {Control} from '../model';

View File

@ -3,7 +3,7 @@ import {EventEmitter, ObservableWrapper} from 'angular2/src/facade/async';
import {QueryList} from 'angular2/core';
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 {Control} from '../model';

View File

@ -40,7 +40,7 @@ import {
Directive,
LifecycleEvent
} 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 {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref';
import {TemplateRef} from 'angular2/src/core/compiler/template_ref';
@ -103,15 +103,15 @@ class OptionallyNeedsDirective {
}
@Injectable()
class NeedsDirectiveFromAncestor {
class NeeedsDirectiveFromHost {
dependency: SimpleDirective;
constructor(@Ancestor() dependency: SimpleDirective) { this.dependency = dependency; }
constructor(@Host() dependency: SimpleDirective) { this.dependency = dependency; }
}
@Injectable()
class NeedsDirectiveFromAnAncestorShadowDom {
class NeedsDirectiveFromHostShadowDom {
dependency: SimpleDirective;
constructor(@Unbounded() dependency: SimpleDirective) { this.dependency = dependency; }
constructor(dependency: SimpleDirective) { this.dependency = dependency; }
}
@Injectable()
@ -121,9 +121,9 @@ class NeedsService {
}
@Injectable()
class NeedsAncestorService {
class NeedsServiceFromHost {
service: any;
constructor(@Ancestor() @Inject("service") service) { this.service = service; }
constructor(@Host() @Inject("service") service) { this.service = service; }
}
class HasEventEmitter {
@ -597,7 +597,7 @@ export function main() {
bind('injectable2')
.toFactory(
(val) => `${val}-injectable2`,
[[new InjectMetadata('injectable1'), new AncestorMetadata()]])
[[new InjectMetadata('injectable1'), new SkipSelfMetadata()]])
]
}))]);
expect(childInj.get('injectable2')).toEqual('injectable1-injectable2');
@ -710,25 +710,25 @@ export function main() {
var inj = injector([NeedsService], imperativelyCreatedInjector);
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)", () => {
var imperativelyCreatedInjector = Injector.resolveAndCreate([
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(NeedsAncestorService).service).toEqual('appService');
expect(inj.get(NeedsServiceFromHost).service).toEqual('appService');
});
it("should instantiate directives that depend on imperatively created injector bindings (child injector)", () => {
var imperativelyCreatedInjector = Injector.resolveAndCreate([
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(NeedsAncestorService).service).toEqual('appService');
expect(inj.get(NeedsServiceFromHost).service).toEqual('appService');
});
it("should prioritize viewInjector over hostInjector for the same binding", () => {
@ -750,7 +750,7 @@ export function main() {
hostInjector: [bind('service').toValue('hostService')]})
)], extraBindings),
ListWrapper.concat([NeedsAncestorService], extraBindings)
ListWrapper.concat([NeedsServiceFromHost], extraBindings)
);
}).toThrowError(new RegExp("No provider for service!"));
});
@ -763,31 +763,31 @@ export function main() {
expect(inj.get(NeedsTemplateRef).templateRef).toEqual(templateRef);
});
it("should get directives from ancestor", () => {
var child = parentChildInjectors(ListWrapper.concat([SimpleDirective], extraBindings),
[NeedsDirectiveFromAncestor]);
it("should get directives", () => {
var child = hostShadowInjectors(
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);
});
it("should get directives crossing the boundaries", () => {
var child = hostShadowInjectors(
ListWrapper.concat([SomeOtherDirective, SimpleDirective], extraBindings),
[NeedsDirectiveFromAnAncestorShadowDom]);
it("should get directives from the host", () => {
var child = parentChildInjectors(ListWrapper.concat([SimpleDirective], extraBindings),
[NeeedsDirectiveFromHost]);
var d = child.get(NeedsDirectiveFromAnAncestorShadowDom);
var d = child.get(NeeedsDirectiveFromHost);
expect(d).toBeAnInstanceOf(NeedsDirectiveFromAnAncestorShadowDom);
expect(d).toBeAnInstanceOf(NeeedsDirectiveFromHost);
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
});
it("should throw when a dependency cannot be resolved", () => {
expect(() => injector(ListWrapper.concat([NeedsDirectiveFromAncestor], extraBindings)))
expect(() => injector(ListWrapper.concat([NeeedsDirectiveFromHost], extraBindings)))
.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", () => {
@ -820,10 +820,10 @@ export function main() {
var directiveBinding =
DirectiveBinding.createFromType(SimpleDirective, new dirAnn.Component());
var shadow = hostShadowInjectors(ListWrapper.concat([directiveBinding], extraBindings),
[NeedsDirectiveFromAncestor]);
[NeeedsDirectiveFromHost]);
var d = shadow.get(NeedsDirectiveFromAncestor);
expect(d).toBeAnInstanceOf(NeedsDirectiveFromAncestor);
var d = shadow.get(NeeedsDirectiveFromHost);
expect(d).toBeAnInstanceOf(NeeedsDirectiveFromHost);
expect(d.dependency).toBeAnInstanceOf(SimpleDirective);
});

View File

@ -44,9 +44,9 @@ import {
forwardRef,
OpaqueToken,
Inject,
Ancestor,
Unbounded,
UnboundedMetadata
Host,
SkipSelf,
SkipSelfMetadata
} from 'angular2/di';
import {
PipeFactory,
@ -435,8 +435,8 @@ export function main() {
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new viewAnn.View({
template:
'<some-directive><toolbar><template toolbarpart var-toolbar-prop="toolbarProp">{{ctxProp}},{{toolbarProp}},<cmp-with-ancestor></cmp-with-ancestor></template></toolbar></some-directive>',
directives: [SomeDirective, CompWithAncestor, ToolbarComponent, ToolbarPart]
'<some-directive><toolbar><template toolbarpart var-toolbar-prop="toolbarProp">{{ctxProp}},{{toolbarProp}},<cmp-with-host></cmp-with-host></template></toolbar></some-directive>',
directives: [SomeDirective, CompWithHost, ToolbarComponent, ToolbarPart]
}))
.createAsync(MyComp)
.then((rootTC) => {
@ -445,7 +445,7 @@ export function main() {
expect(rootTC.nativeElement)
.toHaveText(
'TOOLBAR(From myComp,From toolbar,Component with an injected ancestor)');
'TOOLBAR(From myComp,From toolbar,Component with an injected host)');
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],
(tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new viewAnn.View({
template: `
<some-directive>
<p>
<cmp-with-ancestor #child></cmp-with-ancestor>
<cmp-with-host #child></cmp-with-host>
</p>
</some-directive>`,
directives: [SomeDirective, CompWithAncestor]
directives: [SomeDirective, CompWithHost]
}))
.createAsync(MyComp)
.then((rootTC) => {
var childComponent = rootTC.componentViewChildren[0].getLocal('child');
expect(childComponent.myAncestor).toBeAnInstanceOf(SomeDirective);
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
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) => {
tcb.overrideView(MyComp, new viewAnn.View({
template: `
<some-directive>
<p *ng-if="true">
<cmp-with-ancestor #child></cmp-with-ancestor>
<cmp-with-host #child></cmp-with-host>
</p>
</some-directive>`,
directives: [SomeDirective, CompWithAncestor, NgIf]
directives: [SomeDirective, CompWithHost, NgIf]
}))
.createAsync(MyComp)
@ -716,7 +716,7 @@ export function main() {
var tc = rootTC.componentViewChildren[0].children[1];
var childComponent = tc.getLocal('child');
expect(childComponent.myAncestor).toBeAnInstanceOf(SomeDirective);
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
async.done();
});
@ -1607,12 +1607,12 @@ class SomeDirective {
class SomeDirectiveMissingAnnotation {}
@Component({selector: 'cmp-with-ancestor'})
@View({template: '<p>Component with an injected ancestor</p>', directives: [SomeDirective]})
@Component({selector: 'cmp-with-host'})
@View({template: '<p>Component with an injected host</p>', directives: [SomeDirective]})
@Injectable()
class CompWithAncestor {
myAncestor: SomeDirective;
constructor(@Ancestor() someComp: SomeDirective) { this.myAncestor = someComp; }
class CompWithHost {
myHost: SomeDirective;
constructor(@Host() someComp: SomeDirective) { this.myHost = someComp; }
}
@Component({selector: '[child-cmp2]', viewInjector: [MyService]})
@ -1775,7 +1775,7 @@ class PrivateImpl extends PublicApi {
@Directive({selector: '[needs-public-api]'})
@Injectable()
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]'})
@ -1873,7 +1873,7 @@ class DirectiveProvidingInjectableInHostAndView {
class DirectiveConsumingInjectable {
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 {
injectable;
constructor(@Unbounded() injectable: InjectableService,
@Ancestor() parent: DirectiveContainingDirectiveConsumingAnInjectable) {
constructor(injectable: InjectableService,
@SkipSelf() parent: DirectiveContainingDirectiveConsumingAnInjectable) {
this.injectable = injectable;
parent.directive = this;
}
@ -1927,7 +1927,7 @@ function createParentBus(peb) {
selector: 'parent-providing-event-bus',
hostInjector: [
new Binding(EventBus,
{toFactory: createParentBus, deps: [[EventBus, new UnboundedMetadata()]]})
{toFactory: createParentBus, deps: [[EventBus, new SkipSelfMetadata()]]})
]
})
@View({
@ -1940,7 +1940,7 @@ class ParentProvidingEventBus {
bus: EventBus;
grandParentBus: EventBus;
constructor(bus: EventBus, @Unbounded() grandParentBus: EventBus) {
constructor(bus: EventBus, @SkipSelf() grandParentBus: EventBus) {
this.bus = bus;
this.grandParentBus = grandParentBus;
}
@ -1950,7 +1950,7 @@ class ParentProvidingEventBus {
class ChildConsumingEventBus {
bus: EventBus;
constructor(@Unbounded() bus: EventBus) { this.bus = bus; }
constructor(@SkipSelf() bus: EventBus) { this.bus = bus; }
}
@Directive({selector: '[some-impvp]', properties: ['someImpvp']})

View File

@ -19,8 +19,8 @@ import {
Injectable,
InjectMetadata,
SelfMetadata,
AncestorMetadata,
UnboundedMetadata,
HostMetadata,
SkipSelfMetadata,
Optional,
Inject,
BindingWithVisibility,
@ -420,57 +420,56 @@ export function main() {
});
});
describe("@Ancestor()", () => {
it("should return a dependency from same boundary", () => {
describe("@Host()", () => {
it("should return a dependency from same host", () => {
var parent = Injector.resolveAndCreate([Engine]);
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);
});
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 protoParent = new ProtoInjector([new BindingWithVisibility(engine, PRIVATE)]);
var parent = new Injector(protoParent);
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);
});
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 protoParent = new ProtoInjector([new BindingWithVisibility(engine, PUBLIC)]);
var parent = new Injector(protoParent);
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))
.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 child = parent.resolveAndCreateChild([
bind(Engine)
.toClass(TurboEngine),
bind(Car)
.toFactory((e) => new Car(e), [[Engine, new AncestorMetadata({self: true})]])
bind(Car).toFactory((e) => new Car(e), [[Engine, new HostMetadata()]])
]);
expect(child.get(Car).engine).toBeAnInstanceOf(TurboEngine);
});
});
describe("@Unboudned()", () => {
it("should return a private dependency declared at the boundary", () => {
describe("default", () => {
it("should return a private dependency declared at the host", () => {
var engine = Injector.resolve([Engine])[0];
var protoParent = new ProtoInjector([new BindingWithVisibility(engine, PRIVATE)]);
var parent = new Injector(protoParent);
@ -478,14 +477,14 @@ export function main() {
var child = Injector.resolveAndCreate([
bind(Engine)
.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
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 protoParent = new ProtoInjector([new BindingWithVisibility(engine, PUBLIC)]);
var parent = new Injector(protoParent);
@ -493,14 +492,14 @@ export function main() {
var child = Injector.resolveAndCreate([
bind(Engine)
.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
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 protoParent = new ProtoInjector([new BindingWithVisibility(engine, PRIVATE)]);
var parent = new Injector(protoParent);
@ -508,7 +507,7 @@ export function main() {
var child = Injector.resolveAndCreate([
bind(Engine)
.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);
@ -516,13 +515,12 @@ export function main() {
.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 child = parent.resolveAndCreateChild([
bind(Engine)
.toClass(TurboEngine),
bind(Car)
.toFactory((e) => new Car(e), [[Engine, new UnboundedMetadata({self: true})]])
bind(Car).toFactory((e) => new Car(e), [Engine])
]);
expect(child.get(Car).engine).toBeAnInstanceOf(TurboEngine);

View File

@ -3,7 +3,8 @@ import {
Directive,
View,
ViewEncapsulation,
Ancestor,
Host,
SkipSelf,
ElementRef,
DynamicComponentLoader,
ComponentRef,
@ -212,8 +213,7 @@ export class MdDialogConfig {
})
@View({
templateUrl: 'package:angular2_material/src/components/dialog/dialog.html',
directives: [forwardRef(() => MdDialogContent)],
encapsulation: ViewEncapsulation.NONE
directives: [forwardRef(() => MdDialogContent)]
})
class MdDialogContainer {
// 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'})
class MdDialogContent {
constructor(@Ancestor() dialogContainer: MdDialogContainer, elementRef: ElementRef) {
constructor(@Host() @SkipSelf() dialogContainer: MdDialogContainer, elementRef: ElementRef) {
dialogContainer.contentRef = elementRef;
}
}

View File

@ -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 {StringWrapper, isPresent, isString, NumberWrapper} from 'angular2/src/facade/lang';
@ -244,7 +251,7 @@ export class MdGridTile {
isRegisteredWithGridList: boolean;
constructor(@Ancestor() gridList: MdGridList) {
constructor(@SkipSelf() @Host() gridList: MdGridList) {
this.gridList = gridList;
// Tiles default to 1x1, but rowspan and colspan can be changed via binding.

View File

@ -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';
@ -73,7 +73,7 @@ export class MdInput {
mdChange: EventEmitter;
mdFocusChange: EventEmitter;
constructor(@Attribute('value') value: string, @Ancestor() container: MdInputContainer,
constructor(@Attribute('value') value: string, @SkipSelf() @Host() container: MdInputContainer,
@Attribute('id') id: string) {
// TODO(jelbourn): Remove this when #1402 is done.
this.yes = true;
@ -111,7 +111,7 @@ export class MdInput {
export class MdTextarea extends MdInput {
constructor(
@Attribute('value') value: string,
@Ancestor() container: MdInputContainer,
@SkipSelf() @Host() container: MdInputContainer,
@Attribute('id') id: string) {
super(value, container, id);
}

View File

@ -3,7 +3,8 @@ import {
View,
ViewEncapsulation,
LifecycleEvent,
Ancestor,
Host,
SkipSelf,
Attribute,
Optional
} from 'angular2/angular2';
@ -232,7 +233,7 @@ export class MdRadioButton {
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) {
// Assertions. Ideally these should be stripped out by the compiler.
// TODO(jelbourn): Assert that there's no name binding AND a parent radio group.

View File

@ -6,7 +6,7 @@ import {
Component,
Directive,
View,
Ancestor
Host
} from 'angular2/bootstrap';
import {formDirectives, NgControl, Validators, NgFormModel, FormBuilder} from 'angular2/forms';
@ -50,7 +50,7 @@ class ShowError {
controlPath: string;
errorTypes: List<string>;
constructor(@Ancestor() formDir: NgFormModel) { this.formDir = formDir; }
constructor(@Host() formDir: NgFormModel) { this.formDir = formDir; }
get errorMessage() {
var c = this.formDir.form.find(this.controlPath);

View File

@ -6,7 +6,7 @@ import {
Component,
Directive,
View,
Ancestor,
Host,
NgValidator,
forwardRef,
Binding,

View File

@ -6,7 +6,7 @@ import {
Component,
Directive,
View,
Ancestor,
Host,
NgValidator,
forwardRef,
Binding

View File

@ -6,7 +6,7 @@ import {
Component,
Directive,
View,
Ancestor,
Host,
NgValidator,
forwardRef,
Binding
@ -76,7 +76,7 @@ class ShowError {
controlPath: string;
errorTypes: List<string>;
constructor(@Ancestor() formDir: NgForm) { this.formDir = formDir; }
constructor(@Host() formDir: NgForm) { this.formDir = formDir; }
get errorMessage() {
var c = this.formDir.form.find(this.controlPath);