feat(core): add sugar to use ContentChildren and ViewChildren as prop decorators

Closes #4237
This commit is contained in:
vsavkin 2015-09-17 18:45:49 -07:00 committed by Victor Savkin
parent 5dbe292615
commit 2e9de0b169
2 changed files with 52 additions and 7 deletions

View File

@ -8,7 +8,9 @@ import {
PropertyMetadata, PropertyMetadata,
EventMetadata, EventMetadata,
HostBindingMetadata, HostBindingMetadata,
HostListenerMetadata HostListenerMetadata,
ContentChildrenMetadata,
ViewChildrenMetadata
} from 'angular2/src/core/metadata'; } from 'angular2/src/core/metadata';
import {reflector} from 'angular2/src/core/reflection/reflection'; import {reflector} from 'angular2/src/core/reflection/reflection';
@ -44,6 +46,7 @@ export class DirectiveResolver {
var properties = []; var properties = [];
var events = []; var events = [];
var host = {}; var host = {};
var queries = {};
StringMapWrapper.forEach(propertyMetadata, (metadata: any[], propName: string) => { StringMapWrapper.forEach(propertyMetadata, (metadata: any[], propName: string) => {
metadata.forEach(a => { metadata.forEach(a => {
@ -75,17 +78,28 @@ export class DirectiveResolver {
var args = isPresent(a.args) ? a.args.join(', ') : ''; var args = isPresent(a.args) ? a.args.join(', ') : '';
host[`(${a.eventName})`] = `${propName}(${args})`; host[`(${a.eventName})`] = `${propName}(${args})`;
} }
if (a instanceof ContentChildrenMetadata) {
queries[propName] = a;
}
if (a instanceof ViewChildrenMetadata) {
queries[propName] = a;
}
}); });
}); });
return this._merge(dm, properties, events, host); return this._merge(dm, properties, events, host, queries);
} }
private _merge(dm: DirectiveMetadata, properties: string[], events: string[], private _merge(dm: DirectiveMetadata, properties: string[], events: string[],
host: StringMap<string, string>): DirectiveMetadata { host: StringMap<string, string>,
queries: StringMap<string, any>): DirectiveMetadata {
var mergedProperties = var mergedProperties =
isPresent(dm.properties) ? ListWrapper.concat(dm.properties, properties) : properties; isPresent(dm.properties) ? ListWrapper.concat(dm.properties, properties) : properties;
var mergedEvents = isPresent(dm.events) ? ListWrapper.concat(dm.events, events) : events; var mergedEvents = isPresent(dm.events) ? ListWrapper.concat(dm.events, events) : events;
var mergedHost = isPresent(dm.host) ? StringMapWrapper.merge(dm.host, host) : host; var mergedHost = isPresent(dm.host) ? StringMapWrapper.merge(dm.host, host) : host;
var mergedQueries =
isPresent(dm.queries) ? StringMapWrapper.merge(dm.queries, queries) : queries;
if (dm instanceof ComponentMetadata) { if (dm instanceof ComponentMetadata) {
return new ComponentMetadata({ return new ComponentMetadata({
@ -98,6 +112,7 @@ export class DirectiveResolver {
exportAs: dm.exportAs, exportAs: dm.exportAs,
moduleId: dm.moduleId, moduleId: dm.moduleId,
compileChildren: dm.compileChildren, compileChildren: dm.compileChildren,
queries: mergedQueries,
changeDetection: dm.changeDetection, changeDetection: dm.changeDetection,
viewBindings: dm.viewBindings viewBindings: dm.viewBindings
}); });
@ -111,7 +126,8 @@ export class DirectiveResolver {
bindings: dm.bindings, bindings: dm.bindings,
exportAs: dm.exportAs, exportAs: dm.exportAs,
moduleId: dm.moduleId, moduleId: dm.moduleId,
compileChildren: dm.compileChildren compileChildren: dm.compileChildren,
queries: mergedQueries
}); });
} }
} }

View File

@ -6,7 +6,11 @@ import {
Property, Property,
Event, Event,
HostBinding, HostBinding,
HostListener HostListener,
ContentChildren,
ContentChildrenMetadata,
ViewChildren,
ViewChildrenMetadata
} from 'angular2/src/core/metadata'; } from 'angular2/src/core/metadata';
@Directive({selector: 'someDirective'}) @Directive({selector: 'someDirective'})
@ -64,6 +68,17 @@ class SomeDirectiveWithHostListeners {
} }
} }
@Directive({selector: 'someDirective', queries: {"cs": new ContentChildren("c")}})
class SomeDirectiveWithContentChildren {
@ContentChildren("a") as: any;
c;
}
@Directive({selector: 'someDirective', queries: {"cs": new ViewChildren("c")}})
class SomeDirectiveWithViewChildren {
@ViewChildren("a") as: any;
c;
}
class SomeDirectiveWithoutMetadata {} class SomeDirectiveWithoutMetadata {}
@ -77,7 +92,7 @@ export function main() {
var directiveMetadata = resolver.resolve(SomeDirective); var directiveMetadata = resolver.resolve(SomeDirective);
expect(directiveMetadata) expect(directiveMetadata)
.toEqual(new DirectiveMetadata( .toEqual(new DirectiveMetadata(
{selector: 'someDirective', properties: [], events: [], host: {}})); {selector: 'someDirective', properties: [], events: [], host: {}, queries: {}}));
}); });
it('should throw if not matching metadata is found', () => { it('should throw if not matching metadata is found', () => {
@ -89,7 +104,7 @@ export function main() {
var directiveMetadata = resolver.resolve(SomeChildDirective); var directiveMetadata = resolver.resolve(SomeChildDirective);
expect(directiveMetadata) expect(directiveMetadata)
.toEqual(new DirectiveMetadata( .toEqual(new DirectiveMetadata(
{selector: 'someChildDirective', properties: [], events: [], host: {}})); {selector: 'someChildDirective', properties: [], events: [], host: {}, queries: {}}));
}); });
describe('properties', () => { describe('properties', () => {
@ -128,5 +143,19 @@ export function main() {
.toEqual({'(c)': 'onC()', '(a)': 'onA()', '(b)': 'onB($event.value)'}); .toEqual({'(c)': 'onC()', '(a)': 'onA()', '(b)': 'onB($event.value)'});
}); });
}); });
describe('queries', () => {
it('should append ContentChildren', () => {
var directiveMetadata = resolver.resolve(SomeDirectiveWithContentChildren);
expect(directiveMetadata.queries)
.toEqual({"cs": new ContentChildren("c"), "as": new ContentChildren("a")});
});
it('should append ViewChildren', () => {
var directiveMetadata = resolver.resolve(SomeDirectiveWithViewChildren);
expect(directiveMetadata.queries)
.toEqual({"cs": new ViewChildren("c"), "as": new ViewChildren("a")});
});
});
}); });
} }