feat(core): add support for ContentChildren and ViewChildren
This commit is contained in:
parent
5809a02624
commit
5dbe292615
|
@ -47,6 +47,7 @@ import {
|
|||
} from 'angular2/src/core/change_detection/change_detection';
|
||||
import {QueryList} from './query_list';
|
||||
import {reflector} from 'angular2/src/core/reflection/reflection';
|
||||
import {SetterFn} from 'angular2/src/core/reflection/types';
|
||||
import {RenderDirectiveMetadata} from 'angular2/src/core/render/api';
|
||||
import {EventConfig} from 'angular2/src/core/render/event_config';
|
||||
import {PipeBinding} from '../pipes/pipe_binding';
|
||||
|
@ -138,6 +139,17 @@ export class DirectiveBinding extends ResolvedBinding {
|
|||
|
||||
get callOnDestroy(): boolean { return this.metadata.callOnDestroy; }
|
||||
|
||||
get queries(): QueryMetadataWithSetter[] {
|
||||
if (isBlank(this.metadata.queries)) return [];
|
||||
|
||||
var res = [];
|
||||
StringMapWrapper.forEach(this.metadata.queries, (meta, fieldName) => {
|
||||
var setter = reflector.setter(fieldName);
|
||||
res.push(new QueryMetadataWithSetter(setter, meta));
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
get eventEmitters(): string[] {
|
||||
return isPresent(this.metadata) && isPresent(this.metadata.events) ? this.metadata.events : [];
|
||||
}
|
||||
|
@ -151,6 +163,7 @@ export class DirectiveBinding extends ResolvedBinding {
|
|||
var rf = rb.resolvedFactories[0];
|
||||
var deps = rf.dependencies.map(DirectiveDependency.createFrom);
|
||||
var token = binding.token;
|
||||
|
||||
var metadata = RenderDirectiveMetadata.create({
|
||||
id: stringify(binding.token),
|
||||
type: meta instanceof ComponentMetadata ? RenderDirectiveMetadata.COMPONENT_TYPE :
|
||||
|
@ -161,6 +174,7 @@ export class DirectiveBinding extends ResolvedBinding {
|
|||
host: isPresent(meta.host) ? MapWrapper.createFromStringMap(meta.host) : null,
|
||||
properties: meta.properties,
|
||||
readAttributes: DirectiveBinding._readAttributes(<any>deps),
|
||||
queries: meta.queries,
|
||||
|
||||
callOnDestroy: hasLifecycleHook(LifecycleHooks.OnDestroy, token),
|
||||
callOnChanges: hasLifecycleHook(LifecycleHooks.OnChanges, token),
|
||||
|
@ -203,6 +217,10 @@ export class PreBuiltObjects {
|
|||
public elementRef: ElementRef, public templateRef: TemplateRef) {}
|
||||
}
|
||||
|
||||
export class QueryMetadataWithSetter {
|
||||
constructor(public setter: SetterFn, public metadata: QueryMetadata) {}
|
||||
}
|
||||
|
||||
export class EventEmitterAccessor {
|
||||
constructor(public eventName: string, public getter: Function) {}
|
||||
|
||||
|
@ -214,17 +232,6 @@ export class EventEmitterAccessor {
|
|||
}
|
||||
}
|
||||
|
||||
export class HostActionAccessor {
|
||||
constructor(public methodName: string, public getter: Function) {}
|
||||
|
||||
subscribe(view: viewModule.AppView, boundElementIndex: number, directive: Object): Object {
|
||||
var eventEmitter = this.getter(directive);
|
||||
return ObservableWrapper.subscribe<any[]>(
|
||||
eventEmitter,
|
||||
actionArgs => view.invokeElementMethod(boundElementIndex, this.methodName, actionArgs));
|
||||
}
|
||||
}
|
||||
|
||||
function _createEventEmitterAccessors(bwv: BindingWithVisibility): EventEmitterAccessor[] {
|
||||
var binding = bwv.binding;
|
||||
if (!(binding instanceof DirectiveBinding)) return [];
|
||||
|
@ -554,19 +561,25 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
|
|||
for (var i = 0; i < deps.length; i++) {
|
||||
var dep = deps[i];
|
||||
if (isPresent(dep.queryDecorator)) {
|
||||
this._createQueryRef(dep.queryDecorator);
|
||||
this._createQueryRef(null, null, dep.queryDecorator);
|
||||
}
|
||||
}
|
||||
}
|
||||
_buildQueriesForDirective(dirIndex: number, meta: QueryMetadataWithSetter[]): void {
|
||||
for (var i = 0; i < meta.length; i++) {
|
||||
var m = meta[i];
|
||||
this._createQueryRef(dirIndex, m.setter, m.metadata);
|
||||
}
|
||||
}
|
||||
|
||||
private _createQueryRef(query: QueryMetadata): void {
|
||||
private _createQueryRef(dirIndex: number, setter: SetterFn, query: QueryMetadata): void {
|
||||
var queryList = new QueryList<any>();
|
||||
if (isBlank(this._query0)) {
|
||||
this._query0 = new QueryRef(query, queryList, this);
|
||||
this._query0 = new QueryRef(dirIndex, setter, query, queryList, this);
|
||||
} else if (isBlank(this._query1)) {
|
||||
this._query1 = new QueryRef(query, queryList, this);
|
||||
this._query1 = new QueryRef(dirIndex, setter, query, queryList, this);
|
||||
} else if (isBlank(this._query2)) {
|
||||
this._query2 = new QueryRef(query, queryList, this);
|
||||
this._query2 = new QueryRef(dirIndex, setter, query, queryList, this);
|
||||
} else {
|
||||
throw new QueryError();
|
||||
}
|
||||
|
@ -758,42 +771,54 @@ class ElementInjectorInlineStrategy implements _ElementInjectorStrategy {
|
|||
if (p.binding0 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding0.resolvedFactories[0].dependencies);
|
||||
|
||||
this._ei._buildQueriesForDirective(0, (<DirectiveBinding>p.binding0).queries);
|
||||
}
|
||||
if (p.binding1 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding1.resolvedFactories[0].dependencies);
|
||||
|
||||
this._ei._buildQueriesForDirective(1, (<DirectiveBinding>p.binding1).queries);
|
||||
}
|
||||
if (p.binding2 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding2.resolvedFactories[0].dependencies);
|
||||
this._ei._buildQueriesForDirective(2, (<DirectiveBinding>p.binding2).queries);
|
||||
}
|
||||
if (p.binding3 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding3.resolvedFactories[0].dependencies);
|
||||
this._ei._buildQueriesForDirective(3, (<DirectiveBinding>p.binding3).queries);
|
||||
}
|
||||
if (p.binding4 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding4.resolvedFactories[0].dependencies);
|
||||
this._ei._buildQueriesForDirective(4, (<DirectiveBinding>p.binding4).queries);
|
||||
}
|
||||
if (p.binding5 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding5.resolvedFactories[0].dependencies);
|
||||
this._ei._buildQueriesForDirective(5, (<DirectiveBinding>p.binding5).queries);
|
||||
}
|
||||
if (p.binding6 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding6.resolvedFactories[0].dependencies);
|
||||
this._ei._buildQueriesForDirective(6, (<DirectiveBinding>p.binding6).queries);
|
||||
}
|
||||
if (p.binding7 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding7.resolvedFactories[0].dependencies);
|
||||
this._ei._buildQueriesForDirective(7, (<DirectiveBinding>p.binding7).queries);
|
||||
}
|
||||
if (p.binding8 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding8.resolvedFactories[0].dependencies);
|
||||
this._ei._buildQueriesForDirective(8, (<DirectiveBinding>p.binding8).queries);
|
||||
}
|
||||
if (p.binding9 instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.binding9.resolvedFactories[0].dependencies);
|
||||
this._ei._buildQueriesForDirective(9, (<DirectiveBinding>p.binding9).queries);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -896,6 +921,7 @@ class ElementInjectorDynamicStrategy implements _ElementInjectorStrategy {
|
|||
if (p.bindings[i] instanceof DirectiveBinding) {
|
||||
this._ei._buildQueriesForDeps(
|
||||
<DirectiveDependency[]>p.bindings[i].resolvedFactory.dependencies);
|
||||
this._ei._buildQueriesForDirective(i, (<DirectiveBinding>p.bindings[i]).queries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -927,8 +953,9 @@ export class QueryError extends BaseException {
|
|||
}
|
||||
|
||||
export class QueryRef {
|
||||
constructor(public query: QueryMetadata, public list: QueryList<any>,
|
||||
public originator: ElementInjector, public dirty: boolean = true) {}
|
||||
constructor(public dirIndex: number, public setter: SetterFn, public query: QueryMetadata,
|
||||
public list: QueryList<any>, public originator: ElementInjector,
|
||||
public dirty: boolean = true) {}
|
||||
|
||||
get isViewQuery(): boolean { return this.query.isViewQuery; }
|
||||
|
||||
|
@ -936,6 +963,12 @@ export class QueryRef {
|
|||
if (!this.dirty) return;
|
||||
this._update();
|
||||
this.dirty = false;
|
||||
|
||||
// TODO delete the check once only field queries are supported
|
||||
if (isPresent(this.dirIndex)) {
|
||||
var dir = this.originator.getDirectiveAtIndex(this.dirIndex);
|
||||
this.setter(dir, this.list);
|
||||
}
|
||||
}
|
||||
|
||||
private _update(): void {
|
||||
|
|
|
@ -17,6 +17,7 @@ class Directive extends DirectiveMetadata {
|
|||
const Directive({String selector, List<String> properties,
|
||||
List<String> events, Map<String, String> host,
|
||||
List bindings, String exportAs, String moduleId,
|
||||
Map<String, dynamic> queries,
|
||||
bool compileChildren: true})
|
||||
: super(
|
||||
selector: selector,
|
||||
|
@ -26,6 +27,7 @@ class Directive extends DirectiveMetadata {
|
|||
bindings: bindings,
|
||||
exportAs: exportAs,
|
||||
moduleId: moduleId,
|
||||
queries: queries,
|
||||
compileChildren: compileChildren);
|
||||
}
|
||||
|
||||
|
@ -36,6 +38,7 @@ class Component extends ComponentMetadata {
|
|||
const Component({String selector, List<String> properties,
|
||||
List<String> events, Map<String, String> host, bool dynamicLoadable,
|
||||
List bindings, String exportAs, String moduleId,
|
||||
Map<String, dynamic> queries,
|
||||
bool compileChildren, List viewBindings, ChangeDetectionStrategy changeDetection})
|
||||
: super(
|
||||
selector: selector,
|
||||
|
@ -48,6 +51,7 @@ class Component extends ComponentMetadata {
|
|||
moduleId: moduleId,
|
||||
compileChildren: compileChildren,
|
||||
viewBindings: viewBindings,
|
||||
queries: queries,
|
||||
changeDetection: changeDetection);
|
||||
}
|
||||
|
||||
|
@ -90,6 +94,14 @@ class Query extends QueryMetadata {
|
|||
: super(selector, descendants: descendants);
|
||||
}
|
||||
|
||||
/**
|
||||
* See: [ContentChildrenMetadata] for docs.
|
||||
*/
|
||||
class ContentChildren extends ContentChildrenMetadata {
|
||||
const ContentChildren(dynamic /*Type | string*/ selector, {bool descendants: false})
|
||||
: super(selector, descendants: descendants);
|
||||
}
|
||||
|
||||
/**
|
||||
* See: [ViewQueryMetadata] for docs.
|
||||
*/
|
||||
|
@ -98,6 +110,14 @@ class ViewQuery extends ViewQueryMetadata {
|
|||
: super(selector, descendants: true);
|
||||
}
|
||||
|
||||
/**
|
||||
* See: [ViewChildrenMetadata] for docs.
|
||||
*/
|
||||
class ViewChildren extends ViewChildrenMetadata {
|
||||
const ViewChildren(dynamic /*Type | string*/ selector)
|
||||
: super(selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* See: [PropertyMetadata] for docs.
|
||||
*/
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
export {
|
||||
QueryMetadata,
|
||||
ContentChildrenMetadata,
|
||||
ViewChildrenMetadata,
|
||||
ViewQueryMetadata,
|
||||
AttributeMetadata,
|
||||
} from './metadata/di';
|
||||
|
@ -23,6 +25,8 @@ export {ViewMetadata, ViewEncapsulation} from './metadata/view';
|
|||
|
||||
import {
|
||||
QueryMetadata,
|
||||
ContentChildrenMetadata,
|
||||
ViewChildrenMetadata,
|
||||
ViewQueryMetadata,
|
||||
AttributeMetadata,
|
||||
} from './metadata/di';
|
||||
|
@ -138,12 +142,26 @@ export interface ViewDecorator extends TypeDecorator {
|
|||
*/
|
||||
export interface DirectiveFactory {
|
||||
(obj: {
|
||||
selector?: string, properties?: string[], events?: string[], host?: StringMap<string, string>,
|
||||
bindings?: any[], exportAs?: string, moduleId?: string, compileChildren?: boolean;
|
||||
selector?: string,
|
||||
properties?: string[],
|
||||
events?: string[],
|
||||
host?: StringMap<string, string>,
|
||||
bindings?: any[],
|
||||
exportAs?: string,
|
||||
moduleId?: string,
|
||||
compileChildren?: boolean,
|
||||
queries?: StringMap<string, any>
|
||||
}): DirectiveDecorator;
|
||||
new (obj: {
|
||||
selector?: string, properties?: string[], events?: string[], host?: StringMap<string, string>,
|
||||
bindings?: any[], exportAs?: string, moduleId?: string, compileChildren?: boolean;
|
||||
selector?: string,
|
||||
properties?: string[],
|
||||
events?: string[],
|
||||
host?: StringMap<string, string>,
|
||||
bindings?: any[],
|
||||
exportAs?: string,
|
||||
moduleId?: string,
|
||||
compileChildren?: boolean,
|
||||
queries?: StringMap<string, any>
|
||||
}): DirectiveMetadata;
|
||||
}
|
||||
|
||||
|
@ -201,6 +219,7 @@ export interface ComponentFactory {
|
|||
exportAs?: string,
|
||||
moduleId?: string,
|
||||
compileChildren?: boolean,
|
||||
queries?: StringMap<string, any>,
|
||||
viewBindings?: any[],
|
||||
changeDetection?: ChangeDetectionStrategy,
|
||||
}): ComponentDecorator;
|
||||
|
@ -214,6 +233,7 @@ export interface ComponentFactory {
|
|||
exportAs?: string,
|
||||
moduleId?: string,
|
||||
compileChildren?: boolean,
|
||||
queries?: StringMap<string, any>,
|
||||
viewBindings?: any[],
|
||||
changeDetection?: ChangeDetectionStrategy,
|
||||
}): ComponentMetadata;
|
||||
|
@ -383,6 +403,16 @@ export interface QueryFactory {
|
|||
new (selector: Type | string, {descendants}?: {descendants?: boolean}): QueryMetadata;
|
||||
}
|
||||
|
||||
export interface ContentChildrenFactory {
|
||||
(selector: Type | string, {descendants}?: {descendants?: boolean}): any;
|
||||
new (selector: Type | string, {descendants}?: {descendants?: boolean}): ContentChildrenMetadata;
|
||||
}
|
||||
|
||||
export interface ViewChildrenFactory {
|
||||
(selector: Type | string): any;
|
||||
new (selector: Type | string): ViewChildrenMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link PipeMetadata} factory for creating decorators.
|
||||
*
|
||||
|
@ -511,6 +541,15 @@ export var Attribute: AttributeFactory = makeParamDecorator(AttributeMetadata);
|
|||
*/
|
||||
export var Query: QueryFactory = makeParamDecorator(QueryMetadata);
|
||||
|
||||
/**
|
||||
* {@link ContentChildrenMetadata} factory function.
|
||||
*/
|
||||
export var ContentChildren: ContentChildrenFactory = makePropDecorator(ContentChildrenMetadata);
|
||||
|
||||
/**
|
||||
* {@link ViewChildrenMetadata} factory function.
|
||||
*/
|
||||
export var ViewChildren: ViewChildrenFactory = makePropDecorator(ViewChildrenMetadata);
|
||||
|
||||
/**
|
||||
* {@link ViewQueryMetadata} factory function.
|
||||
|
|
|
@ -201,6 +201,34 @@ export class QueryMetadata extends DependencyMetadata {
|
|||
toString(): string { return `@Query(${stringify(this.selector)})`; }
|
||||
}
|
||||
|
||||
// TODO: add an example after ContentChildren and ViewChildren are in master
|
||||
/**
|
||||
* Configures a content query.
|
||||
*
|
||||
* Content queries are set before the `afterContentInit` callback is called.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* ```
|
||||
* @Directive({
|
||||
* selector: 'someDir'
|
||||
* })
|
||||
* class SomeDir {
|
||||
* @ContentChildren(ChildDirective) contentChildren: QueryList<ChildDirective>;
|
||||
*
|
||||
* afterContentInit() {
|
||||
* // contentChildren is set
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@CONST()
|
||||
export class ContentChildrenMetadata extends QueryMetadata {
|
||||
constructor(_selector: Type | string, {descendants = false}: {descendants?: boolean} = {}) {
|
||||
super(_selector, {descendants: descendants});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link QueryMetadata}, but querying the component view, instead of
|
||||
* the content children.
|
||||
|
@ -248,3 +276,29 @@ export class ViewQueryMetadata extends QueryMetadata {
|
|||
get isViewQuery() { return true; }
|
||||
toString(): string { return `@ViewQuery(${stringify(this.selector)})`; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a view query.
|
||||
*
|
||||
* View queries are set before the `afterViewInit` callback is called.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* ```
|
||||
* @Component({
|
||||
* selector: 'someDir'
|
||||
* })
|
||||
* @View({templateUrl: 'someTemplate', directives: [ItemDirective]})
|
||||
* class SomeDir {
|
||||
* @ViewChildren(ItemDirective) viewChildren: QueryList<ItemDirective>;
|
||||
*
|
||||
* afterViewInit() {
|
||||
* // viewChildren is set
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@CONST()
|
||||
export class ViewChildrenMetadata extends ViewQueryMetadata {
|
||||
constructor(_selector: Type | string) { super(_selector, {descendants: true}); }
|
||||
}
|
||||
|
|
|
@ -719,8 +719,45 @@ export class DirectiveMetadata extends InjectableMetadata {
|
|||
*/
|
||||
moduleId: string;
|
||||
|
||||
// TODO: add an example after ContentChildren and ViewChildren are in master
|
||||
/**
|
||||
* Configures the queries that will be injected into the directive.
|
||||
*
|
||||
* Content queries are set before the `afterContentInit` callback is called.
|
||||
* View queries are set before the `afterViewInit` callback is called.
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* ```
|
||||
* @Component({
|
||||
* selector: 'someDir',
|
||||
* queries: {
|
||||
* contentChildren: new ContentChildren(ChildDirective),
|
||||
* viewChildren: new ViewChildren(ChildDirective)
|
||||
* }
|
||||
* })
|
||||
* @View({
|
||||
* template: '<child-directive></child-directive>',
|
||||
* directives: [ChildDirective]
|
||||
* })
|
||||
* class SomeDir {
|
||||
* contentChildren: QueryList<ChildDirective>,
|
||||
* viewChildren: QueryList<ChildDirective>
|
||||
*
|
||||
* afterContentInit() {
|
||||
* // contentChildren is set
|
||||
* }
|
||||
*
|
||||
* afterViewInit() {
|
||||
* // viewChildren is set
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
queries: StringMap<string, any>;
|
||||
|
||||
constructor({
|
||||
selector, properties, events, host, bindings, exportAs, moduleId,
|
||||
selector, properties, events, host, bindings, exportAs, moduleId, queries,
|
||||
compileChildren = true,
|
||||
}: {
|
||||
selector?: string,
|
||||
|
@ -730,6 +767,7 @@ export class DirectiveMetadata extends InjectableMetadata {
|
|||
bindings?: any[],
|
||||
exportAs?: string,
|
||||
moduleId?: string,
|
||||
queries?: StringMap<string, any>,
|
||||
compileChildren?: boolean,
|
||||
} = {}) {
|
||||
super();
|
||||
|
@ -739,6 +777,7 @@ export class DirectiveMetadata extends InjectableMetadata {
|
|||
this.host = host;
|
||||
this.exportAs = exportAs;
|
||||
this.moduleId = moduleId;
|
||||
this.queries = queries;
|
||||
this.compileChildren = compileChildren;
|
||||
this.bindings = bindings;
|
||||
}
|
||||
|
@ -862,7 +901,7 @@ export class ComponentMetadata extends DirectiveMetadata {
|
|||
viewBindings: any[];
|
||||
|
||||
constructor({selector, properties, events, host, dynamicLoadable, exportAs, moduleId, bindings,
|
||||
viewBindings, changeDetection = ChangeDetectionStrategy.Default,
|
||||
queries, viewBindings, changeDetection = ChangeDetectionStrategy.Default,
|
||||
compileChildren = true}: {
|
||||
selector?: string,
|
||||
properties?: string[],
|
||||
|
@ -874,6 +913,7 @@ export class ComponentMetadata extends DirectiveMetadata {
|
|||
moduleId?: string,
|
||||
compileChildren?: boolean,
|
||||
viewBindings?: any[],
|
||||
queries?: StringMap<string, any>,
|
||||
changeDetection?: ChangeDetectionStrategy,
|
||||
} = {}) {
|
||||
super({
|
||||
|
@ -884,6 +924,7 @@ export class ComponentMetadata extends DirectiveMetadata {
|
|||
exportAs: exportAs,
|
||||
moduleId: moduleId,
|
||||
bindings: bindings,
|
||||
queries: queries,
|
||||
compileChildren: compileChildren
|
||||
});
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ export class RenderDirectiveMetadata {
|
|||
hostListeners: Map<string, string>;
|
||||
hostProperties: Map<string, string>;
|
||||
hostAttributes: Map<string, string>;
|
||||
queries: StringMap<string, any>;
|
||||
// group 1: "property" from "[property]"
|
||||
// group 2: "event" from "(event)"
|
||||
private static _hostRegExp = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
|
||||
|
@ -167,7 +168,7 @@ export class RenderDirectiveMetadata {
|
|||
constructor({id, selector, compileChildren, events, hostListeners, hostProperties, hostAttributes,
|
||||
properties, readAttributes, type, callOnDestroy, callOnChanges, callDoCheck,
|
||||
callOnInit, callAfterContentInit, callAfterContentChecked, callAfterViewInit,
|
||||
callAfterViewChecked, changeDetection, exportAs}: {
|
||||
callAfterViewChecked, changeDetection, exportAs, queries}: {
|
||||
id?: string,
|
||||
selector?: string,
|
||||
compileChildren?: boolean,
|
||||
|
@ -187,7 +188,8 @@ export class RenderDirectiveMetadata {
|
|||
callAfterViewInit?: boolean,
|
||||
callAfterViewChecked?: boolean,
|
||||
changeDetection?: ChangeDetectionStrategy,
|
||||
exportAs?: string
|
||||
exportAs?: string,
|
||||
queries?: StringMap<string, any>
|
||||
}) {
|
||||
this.id = id;
|
||||
this.selector = selector;
|
||||
|
@ -209,12 +211,13 @@ export class RenderDirectiveMetadata {
|
|||
this.callAfterViewChecked = callAfterViewChecked;
|
||||
this.changeDetection = changeDetection;
|
||||
this.exportAs = exportAs;
|
||||
this.queries = queries;
|
||||
}
|
||||
|
||||
static create({id, selector, compileChildren, events, host, properties, readAttributes, type,
|
||||
callOnDestroy, callOnChanges, callDoCheck, callOnInit, callAfterContentInit,
|
||||
callAfterContentChecked, callAfterViewInit, callAfterViewChecked, changeDetection,
|
||||
exportAs}: {
|
||||
exportAs, queries}: {
|
||||
id?: string,
|
||||
selector?: string,
|
||||
compileChildren?: boolean,
|
||||
|
@ -232,7 +235,8 @@ export class RenderDirectiveMetadata {
|
|||
callAfterViewInit?: boolean,
|
||||
callAfterViewChecked?: boolean,
|
||||
changeDetection?: ChangeDetectionStrategy,
|
||||
exportAs?: string
|
||||
exportAs?: string,
|
||||
queries?: StringMap<string, any>
|
||||
}): RenderDirectiveMetadata {
|
||||
let hostListeners = new Map();
|
||||
let hostProperties = new Map();
|
||||
|
@ -271,7 +275,8 @@ export class RenderDirectiveMetadata {
|
|||
callAfterViewInit: callAfterViewInit,
|
||||
callAfterViewChecked: callAfterViewChecked,
|
||||
changeDetection: changeDetection,
|
||||
exportAs: exportAs
|
||||
exportAs: exportAs,
|
||||
queries: queries
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ export class MockDirectiveResolver extends DirectiveResolver {
|
|||
exportAs: dm.exportAs,
|
||||
moduleId: dm.moduleId,
|
||||
compileChildren: dm.compileChildren,
|
||||
queries: dm.queries,
|
||||
changeDetection: dm.changeDetection,
|
||||
viewBindings: viewBindings
|
||||
});
|
||||
|
@ -47,7 +48,8 @@ export class MockDirectiveResolver extends DirectiveResolver {
|
|||
bindings: bindings,
|
||||
exportAs: dm.exportAs,
|
||||
moduleId: dm.moduleId,
|
||||
compileChildren: dm.compileChildren
|
||||
compileChildren: dm.compileChildren,
|
||||
queries: dm.queries
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,11 @@ import {
|
|||
Query,
|
||||
QueryList,
|
||||
View,
|
||||
ViewQuery
|
||||
ViewQuery,
|
||||
ContentChildren,
|
||||
ViewChildren,
|
||||
AfterContentInit,
|
||||
AfterViewInit
|
||||
} from 'angular2/core';
|
||||
|
||||
import {asNativeElements} from 'angular2/src/core/debug';
|
||||
|
@ -36,7 +40,7 @@ export function main() {
|
|||
describe('Query API', () => {
|
||||
|
||||
describe("querying by directive type", () => {
|
||||
it('should contain all direct child directives in the light dom',
|
||||
it('should contain all direct child directives in the light dom (constructor)',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template = '<div text="1"></div>' +
|
||||
'<needs-query text="2"><div text="3">' +
|
||||
|
@ -56,6 +60,27 @@ export function main() {
|
|||
});
|
||||
}));
|
||||
|
||||
it('should contain all direct child directives in the content dom',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template =
|
||||
'<needs-content-children #q><div text="foo"></div></needs-content-children>';
|
||||
|
||||
tcb.overrideTemplate(MyComp, template)
|
||||
.createAsync(MyComp)
|
||||
.then((view) => {
|
||||
view.detectChanges();
|
||||
|
||||
var q = view.debugElement.componentViewChildren[0].getLocal('q');
|
||||
|
||||
view.detectChanges();
|
||||
|
||||
expect(q.textDirChildren.length).toEqual(1);
|
||||
expect(q.numberOfChildrenAfterContentInit).toEqual(1);
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should contain all directives in the light dom when descendants flag is used',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template = '<div text="1"></div>' +
|
||||
|
@ -385,6 +410,27 @@ export function main() {
|
|||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should contain all child directives in the view dom',
|
||||
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
|
||||
var template = '<needs-view-children #q></needs-view-children>';
|
||||
|
||||
tcb.overrideTemplate(MyComp, template)
|
||||
.createAsync(MyComp)
|
||||
.then((view) => {
|
||||
view.detectChanges();
|
||||
|
||||
var q = view.debugElement.componentViewChildren[0].getLocal('q');
|
||||
|
||||
view.detectChanges();
|
||||
|
||||
expect(q.textDirChildren.length).toEqual(1);
|
||||
expect(q.numberOfChildrenAfterViewInit).toEqual(1);
|
||||
|
||||
async.done();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe("querying in the view", () => {
|
||||
|
@ -552,6 +598,32 @@ class TextDirective {
|
|||
constructor() {}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'needs-content-children',
|
||||
queries: {'textDirChildren': new ContentChildren(TextDirective)}
|
||||
})
|
||||
@View({template: ''})
|
||||
class NeedsContentChildren implements AfterContentInit {
|
||||
textDirChildren: QueryList<TextDirective>;
|
||||
numberOfChildrenAfterContentInit: number;
|
||||
|
||||
afterContentInit() { this.numberOfChildrenAfterContentInit = this.textDirChildren.length; }
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'needs-view-children',
|
||||
queries: {
|
||||
'textDirChildren': new ViewChildren(TextDirective),
|
||||
}
|
||||
})
|
||||
@View({template: '<div text></div>', directives: [TextDirective]})
|
||||
class NeedsViewChildren implements AfterViewInit {
|
||||
textDirChildren: QueryList<TextDirective>;
|
||||
numberOfChildrenAfterViewInit: number;
|
||||
|
||||
afterViewInit() { this.numberOfChildrenAfterViewInit = this.textDirChildren.length; }
|
||||
}
|
||||
|
||||
@Directive({selector: '[dir]'})
|
||||
@Injectable()
|
||||
class InertDirective {
|
||||
|
@ -718,6 +790,8 @@ class NeedsTpl {
|
|||
NeedsViewQueryOrder,
|
||||
NeedsViewQueryByLabel,
|
||||
NeedsViewQueryOrderWithParent,
|
||||
NeedsContentChildren,
|
||||
NeedsViewChildren,
|
||||
NeedsTpl,
|
||||
TextDirective,
|
||||
InertDirective,
|
||||
|
|
|
@ -180,6 +180,30 @@ const NG_API = [
|
|||
'ComponentUrlMapper',
|
||||
'ComponentUrlMapper.getUrl',
|
||||
|
||||
'ContentChildren',
|
||||
'ContentChildren.constructor',
|
||||
'ContentChildren.constructor.constructor',
|
||||
'ContentChildren.constructor.isVarBindingQuery',
|
||||
'ContentChildren.constructor.isViewQuery',
|
||||
'ContentChildren.constructor.selector',
|
||||
'ContentChildren.constructor.toString',
|
||||
'ContentChildren.constructor.token',
|
||||
'ContentChildren.constructor.varBindings',
|
||||
'ContentChildren.isVarBindingQuery',
|
||||
'ContentChildren.isViewQuery',
|
||||
'ContentChildren.selector',
|
||||
'ContentChildren.toString',
|
||||
'ContentChildren.token',
|
||||
'ContentChildren.varBindings',
|
||||
'ContentChildrenMetadata',
|
||||
'ContentChildrenMetadata.constructor',
|
||||
'ContentChildrenMetadata.isVarBindingQuery',
|
||||
'ContentChildrenMetadata.isViewQuery',
|
||||
'ContentChildrenMetadata.selector',
|
||||
'ContentChildrenMetadata.toString',
|
||||
'ContentChildrenMetadata.token',
|
||||
'ContentChildrenMetadata.varBindings',
|
||||
|
||||
'Control',
|
||||
'Control.constructor',
|
||||
'Control.dirty',
|
||||
|
@ -836,6 +860,30 @@ const NG_API = [
|
|||
|
||||
'View',
|
||||
|
||||
'ViewChildren',
|
||||
'ViewChildren.constructor',
|
||||
'ViewChildren.constructor.constructor',
|
||||
'ViewChildren.constructor.isVarBindingQuery',
|
||||
'ViewChildren.constructor.isViewQuery',
|
||||
'ViewChildren.constructor.selector',
|
||||
'ViewChildren.constructor.toString',
|
||||
'ViewChildren.constructor.token',
|
||||
'ViewChildren.constructor.varBindings',
|
||||
'ViewChildren.isVarBindingQuery',
|
||||
'ViewChildren.isViewQuery',
|
||||
'ViewChildren.selector',
|
||||
'ViewChildren.toString',
|
||||
'ViewChildren.token',
|
||||
'ViewChildren.varBindings',
|
||||
'ViewChildrenMetadata',
|
||||
'ViewChildrenMetadata.constructor',
|
||||
'ViewChildrenMetadata.isVarBindingQuery',
|
||||
'ViewChildrenMetadata.isViewQuery',
|
||||
'ViewChildrenMetadata.selector',
|
||||
'ViewChildrenMetadata.toString',
|
||||
'ViewChildrenMetadata.token',
|
||||
'ViewChildrenMetadata.varBindings',
|
||||
|
||||
'ViewContainerRef',
|
||||
'ViewContainerRef.clear',
|
||||
'ViewContainerRef.createEmbeddedView',
|
||||
|
|
Loading…
Reference in New Issue