X Tutup
Skip to content

Commit 5dbe292

Browse files
committed
feat(core): add support for ContentChildren and ViewChildren
1 parent 5809a02 commit 5dbe292

File tree

9 files changed

+348
-32
lines changed

9 files changed

+348
-32
lines changed

modules/angular2/src/core/compiler/element_injector.ts

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import {
4747
} from 'angular2/src/core/change_detection/change_detection';
4848
import {QueryList} from './query_list';
4949
import {reflector} from 'angular2/src/core/reflection/reflection';
50+
import {SetterFn} from 'angular2/src/core/reflection/types';
5051
import {RenderDirectiveMetadata} from 'angular2/src/core/render/api';
5152
import {EventConfig} from 'angular2/src/core/render/event_config';
5253
import {PipeBinding} from '../pipes/pipe_binding';
@@ -138,6 +139,17 @@ export class DirectiveBinding extends ResolvedBinding {
138139

139140
get callOnDestroy(): boolean { return this.metadata.callOnDestroy; }
140141

142+
get queries(): QueryMetadataWithSetter[] {
143+
if (isBlank(this.metadata.queries)) return [];
144+
145+
var res = [];
146+
StringMapWrapper.forEach(this.metadata.queries, (meta, fieldName) => {
147+
var setter = reflector.setter(fieldName);
148+
res.push(new QueryMetadataWithSetter(setter, meta));
149+
});
150+
return res;
151+
}
152+
141153
get eventEmitters(): string[] {
142154
return isPresent(this.metadata) && isPresent(this.metadata.events) ? this.metadata.events : [];
143155
}
@@ -151,6 +163,7 @@ export class DirectiveBinding extends ResolvedBinding {
151163
var rf = rb.resolvedFactories[0];
152164
var deps = rf.dependencies.map(DirectiveDependency.createFrom);
153165
var token = binding.token;
166+
154167
var metadata = RenderDirectiveMetadata.create({
155168
id: stringify(binding.token),
156169
type: meta instanceof ComponentMetadata ? RenderDirectiveMetadata.COMPONENT_TYPE :
@@ -161,6 +174,7 @@ export class DirectiveBinding extends ResolvedBinding {
161174
host: isPresent(meta.host) ? MapWrapper.createFromStringMap(meta.host) : null,
162175
properties: meta.properties,
163176
readAttributes: DirectiveBinding._readAttributes(<any>deps),
177+
queries: meta.queries,
164178

165179
callOnDestroy: hasLifecycleHook(LifecycleHooks.OnDestroy, token),
166180
callOnChanges: hasLifecycleHook(LifecycleHooks.OnChanges, token),
@@ -203,6 +217,10 @@ export class PreBuiltObjects {
203217
public elementRef: ElementRef, public templateRef: TemplateRef) {}
204218
}
205219

220+
export class QueryMetadataWithSetter {
221+
constructor(public setter: SetterFn, public metadata: QueryMetadata) {}
222+
}
223+
206224
export class EventEmitterAccessor {
207225
constructor(public eventName: string, public getter: Function) {}
208226

@@ -214,17 +232,6 @@ export class EventEmitterAccessor {
214232
}
215233
}
216234

217-
export class HostActionAccessor {
218-
constructor(public methodName: string, public getter: Function) {}
219-
220-
subscribe(view: viewModule.AppView, boundElementIndex: number, directive: Object): Object {
221-
var eventEmitter = this.getter(directive);
222-
return ObservableWrapper.subscribe<any[]>(
223-
eventEmitter,
224-
actionArgs => view.invokeElementMethod(boundElementIndex, this.methodName, actionArgs));
225-
}
226-
}
227-
228235
function _createEventEmitterAccessors(bwv: BindingWithVisibility): EventEmitterAccessor[] {
229236
var binding = bwv.binding;
230237
if (!(binding instanceof DirectiveBinding)) return [];
@@ -554,19 +561,25 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
554561
for (var i = 0; i < deps.length; i++) {
555562
var dep = deps[i];
556563
if (isPresent(dep.queryDecorator)) {
557-
this._createQueryRef(dep.queryDecorator);
564+
this._createQueryRef(null, null, dep.queryDecorator);
558565
}
559566
}
560567
}
568+
_buildQueriesForDirective(dirIndex: number, meta: QueryMetadataWithSetter[]): void {
569+
for (var i = 0; i < meta.length; i++) {
570+
var m = meta[i];
571+
this._createQueryRef(dirIndex, m.setter, m.metadata);
572+
}
573+
}
561574

562-
private _createQueryRef(query: QueryMetadata): void {
575+
private _createQueryRef(dirIndex: number, setter: SetterFn, query: QueryMetadata): void {
563576
var queryList = new QueryList<any>();
564577
if (isBlank(this._query0)) {
565-
this._query0 = new QueryRef(query, queryList, this);
578+
this._query0 = new QueryRef(dirIndex, setter, query, queryList, this);
566579
} else if (isBlank(this._query1)) {
567-
this._query1 = new QueryRef(query, queryList, this);
580+
this._query1 = new QueryRef(dirIndex, setter, query, queryList, this);
568581
} else if (isBlank(this._query2)) {
569-
this._query2 = new QueryRef(query, queryList, this);
582+
this._query2 = new QueryRef(dirIndex, setter, query, queryList, this);
570583
} else {
571584
throw new QueryError();
572585
}
@@ -758,42 +771,54 @@ class ElementInjectorInlineStrategy implements _ElementInjectorStrategy {
758771
if (p.binding0 instanceof DirectiveBinding) {
759772
this._ei._buildQueriesForDeps(
760773
<DirectiveDependency[]>p.binding0.resolvedFactories[0].dependencies);
774+
775+
this._ei._buildQueriesForDirective(0, (<DirectiveBinding>p.binding0).queries);
761776
}
762777
if (p.binding1 instanceof DirectiveBinding) {
763778
this._ei._buildQueriesForDeps(
764779
<DirectiveDependency[]>p.binding1.resolvedFactories[0].dependencies);
780+
781+
this._ei._buildQueriesForDirective(1, (<DirectiveBinding>p.binding1).queries);
765782
}
766783
if (p.binding2 instanceof DirectiveBinding) {
767784
this._ei._buildQueriesForDeps(
768785
<DirectiveDependency[]>p.binding2.resolvedFactories[0].dependencies);
786+
this._ei._buildQueriesForDirective(2, (<DirectiveBinding>p.binding2).queries);
769787
}
770788
if (p.binding3 instanceof DirectiveBinding) {
771789
this._ei._buildQueriesForDeps(
772790
<DirectiveDependency[]>p.binding3.resolvedFactories[0].dependencies);
791+
this._ei._buildQueriesForDirective(3, (<DirectiveBinding>p.binding3).queries);
773792
}
774793
if (p.binding4 instanceof DirectiveBinding) {
775794
this._ei._buildQueriesForDeps(
776795
<DirectiveDependency[]>p.binding4.resolvedFactories[0].dependencies);
796+
this._ei._buildQueriesForDirective(4, (<DirectiveBinding>p.binding4).queries);
777797
}
778798
if (p.binding5 instanceof DirectiveBinding) {
779799
this._ei._buildQueriesForDeps(
780800
<DirectiveDependency[]>p.binding5.resolvedFactories[0].dependencies);
801+
this._ei._buildQueriesForDirective(5, (<DirectiveBinding>p.binding5).queries);
781802
}
782803
if (p.binding6 instanceof DirectiveBinding) {
783804
this._ei._buildQueriesForDeps(
784805
<DirectiveDependency[]>p.binding6.resolvedFactories[0].dependencies);
806+
this._ei._buildQueriesForDirective(6, (<DirectiveBinding>p.binding6).queries);
785807
}
786808
if (p.binding7 instanceof DirectiveBinding) {
787809
this._ei._buildQueriesForDeps(
788810
<DirectiveDependency[]>p.binding7.resolvedFactories[0].dependencies);
811+
this._ei._buildQueriesForDirective(7, (<DirectiveBinding>p.binding7).queries);
789812
}
790813
if (p.binding8 instanceof DirectiveBinding) {
791814
this._ei._buildQueriesForDeps(
792815
<DirectiveDependency[]>p.binding8.resolvedFactories[0].dependencies);
816+
this._ei._buildQueriesForDirective(8, (<DirectiveBinding>p.binding8).queries);
793817
}
794818
if (p.binding9 instanceof DirectiveBinding) {
795819
this._ei._buildQueriesForDeps(
796820
<DirectiveDependency[]>p.binding9.resolvedFactories[0].dependencies);
821+
this._ei._buildQueriesForDirective(9, (<DirectiveBinding>p.binding9).queries);
797822
}
798823
}
799824

@@ -896,6 +921,7 @@ class ElementInjectorDynamicStrategy implements _ElementInjectorStrategy {
896921
if (p.bindings[i] instanceof DirectiveBinding) {
897922
this._ei._buildQueriesForDeps(
898923
<DirectiveDependency[]>p.bindings[i].resolvedFactory.dependencies);
924+
this._ei._buildQueriesForDirective(i, (<DirectiveBinding>p.bindings[i]).queries);
899925
}
900926
}
901927
}
@@ -927,15 +953,22 @@ export class QueryError extends BaseException {
927953
}
928954

929955
export class QueryRef {
930-
constructor(public query: QueryMetadata, public list: QueryList<any>,
931-
public originator: ElementInjector, public dirty: boolean = true) {}
956+
constructor(public dirIndex: number, public setter: SetterFn, public query: QueryMetadata,
957+
public list: QueryList<any>, public originator: ElementInjector,
958+
public dirty: boolean = true) {}
932959

933960
get isViewQuery(): boolean { return this.query.isViewQuery; }
934961

935962
update(): void {
936963
if (!this.dirty) return;
937964
this._update();
938965
this.dirty = false;
966+
967+
// TODO delete the check once only field queries are supported
968+
if (isPresent(this.dirIndex)) {
969+
var dir = this.originator.getDirectiveAtIndex(this.dirIndex);
970+
this.setter(dir, this.list);
971+
}
939972
}
940973

941974
private _update(): void {

modules/angular2/src/core/metadata.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Directive extends DirectiveMetadata {
1717
const Directive({String selector, List<String> properties,
1818
List<String> events, Map<String, String> host,
1919
List bindings, String exportAs, String moduleId,
20+
Map<String, dynamic> queries,
2021
bool compileChildren: true})
2122
: super(
2223
selector: selector,
@@ -26,6 +27,7 @@ class Directive extends DirectiveMetadata {
2627
bindings: bindings,
2728
exportAs: exportAs,
2829
moduleId: moduleId,
30+
queries: queries,
2931
compileChildren: compileChildren);
3032
}
3133

@@ -36,6 +38,7 @@ class Component extends ComponentMetadata {
3638
const Component({String selector, List<String> properties,
3739
List<String> events, Map<String, String> host, bool dynamicLoadable,
3840
List bindings, String exportAs, String moduleId,
41+
Map<String, dynamic> queries,
3942
bool compileChildren, List viewBindings, ChangeDetectionStrategy changeDetection})
4043
: super(
4144
selector: selector,
@@ -48,6 +51,7 @@ class Component extends ComponentMetadata {
4851
moduleId: moduleId,
4952
compileChildren: compileChildren,
5053
viewBindings: viewBindings,
54+
queries: queries,
5155
changeDetection: changeDetection);
5256
}
5357

@@ -90,6 +94,14 @@ class Query extends QueryMetadata {
9094
: super(selector, descendants: descendants);
9195
}
9296

97+
/**
98+
* See: [ContentChildrenMetadata] for docs.
99+
*/
100+
class ContentChildren extends ContentChildrenMetadata {
101+
const ContentChildren(dynamic /*Type | string*/ selector, {bool descendants: false})
102+
: super(selector, descendants: descendants);
103+
}
104+
93105
/**
94106
* See: [ViewQueryMetadata] for docs.
95107
*/
@@ -98,6 +110,14 @@ class ViewQuery extends ViewQueryMetadata {
98110
: super(selector, descendants: true);
99111
}
100112

113+
/**
114+
* See: [ViewChildrenMetadata] for docs.
115+
*/
116+
class ViewChildren extends ViewChildrenMetadata {
117+
const ViewChildren(dynamic /*Type | string*/ selector)
118+
: super(selector);
119+
}
120+
101121
/**
102122
* See: [PropertyMetadata] for docs.
103123
*/

modules/angular2/src/core/metadata.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
export {
77
QueryMetadata,
8+
ContentChildrenMetadata,
9+
ViewChildrenMetadata,
810
ViewQueryMetadata,
911
AttributeMetadata,
1012
} from './metadata/di';
@@ -23,6 +25,8 @@ export {ViewMetadata, ViewEncapsulation} from './metadata/view';
2325

2426
import {
2527
QueryMetadata,
28+
ContentChildrenMetadata,
29+
ViewChildrenMetadata,
2630
ViewQueryMetadata,
2731
AttributeMetadata,
2832
} from './metadata/di';
@@ -138,12 +142,26 @@ export interface ViewDecorator extends TypeDecorator {
138142
*/
139143
export interface DirectiveFactory {
140144
(obj: {
141-
selector?: string, properties?: string[], events?: string[], host?: StringMap<string, string>,
142-
bindings?: any[], exportAs?: string, moduleId?: string, compileChildren?: boolean;
145+
selector?: string,
146+
properties?: string[],
147+
events?: string[],
148+
host?: StringMap<string, string>,
149+
bindings?: any[],
150+
exportAs?: string,
151+
moduleId?: string,
152+
compileChildren?: boolean,
153+
queries?: StringMap<string, any>
143154
}): DirectiveDecorator;
144155
new (obj: {
145-
selector?: string, properties?: string[], events?: string[], host?: StringMap<string, string>,
146-
bindings?: any[], exportAs?: string, moduleId?: string, compileChildren?: boolean;
156+
selector?: string,
157+
properties?: string[],
158+
events?: string[],
159+
host?: StringMap<string, string>,
160+
bindings?: any[],
161+
exportAs?: string,
162+
moduleId?: string,
163+
compileChildren?: boolean,
164+
queries?: StringMap<string, any>
147165
}): DirectiveMetadata;
148166
}
149167

@@ -201,6 +219,7 @@ export interface ComponentFactory {
201219
exportAs?: string,
202220
moduleId?: string,
203221
compileChildren?: boolean,
222+
queries?: StringMap<string, any>,
204223
viewBindings?: any[],
205224
changeDetection?: ChangeDetectionStrategy,
206225
}): ComponentDecorator;
@@ -214,6 +233,7 @@ export interface ComponentFactory {
214233
exportAs?: string,
215234
moduleId?: string,
216235
compileChildren?: boolean,
236+
queries?: StringMap<string, any>,
217237
viewBindings?: any[],
218238
changeDetection?: ChangeDetectionStrategy,
219239
}): ComponentMetadata;
@@ -383,6 +403,16 @@ export interface QueryFactory {
383403
new (selector: Type | string, {descendants}?: {descendants?: boolean}): QueryMetadata;
384404
}
385405

406+
export interface ContentChildrenFactory {
407+
(selector: Type | string, {descendants}?: {descendants?: boolean}): any;
408+
new (selector: Type | string, {descendants}?: {descendants?: boolean}): ContentChildrenMetadata;
409+
}
410+
411+
export interface ViewChildrenFactory {
412+
(selector: Type | string): any;
413+
new (selector: Type | string): ViewChildrenMetadata;
414+
}
415+
386416
/**
387417
* {@link PipeMetadata} factory for creating decorators.
388418
*
@@ -511,6 +541,15 @@ export var Attribute: AttributeFactory = makeParamDecorator(AttributeMetadata);
511541
*/
512542
export var Query: QueryFactory = makeParamDecorator(QueryMetadata);
513543

544+
/**
545+
* {@link ContentChildrenMetadata} factory function.
546+
*/
547+
export var ContentChildren: ContentChildrenFactory = makePropDecorator(ContentChildrenMetadata);
548+
549+
/**
550+
* {@link ViewChildrenMetadata} factory function.
551+
*/
552+
export var ViewChildren: ViewChildrenFactory = makePropDecorator(ViewChildrenMetadata);
514553

515554
/**
516555
* {@link ViewQueryMetadata} factory function.

0 commit comments

Comments
 (0)
X Tutup