Skip to content

Commit 2882ca5

Browse files
tboschgoderbauer
authored andcommitted
feat(query): allow to query for TemplateRef
Part of angular#1989 Closes angular#3202
1 parent 4a6d8ef commit 2882ca5

File tree

5 files changed

+61
-6
lines changed

5 files changed

+61
-6
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,10 @@ export class ElementInjector extends TreeNode<ElementInjector> implements Depend
714714
}
715715

716716
addDirectivesMatchingQuery(query: Query, list: any[]): void {
717+
var templateRef = this._preBuiltObjects.templateRef;
718+
if (query.selector === TemplateRef && isPresent(templateRef)) {
719+
list.push(templateRef);
720+
}
717721
this._strategy.addDirectivesMatchingQuery(query, list);
718722
}
719723

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,10 +366,13 @@ function _createProtoElementInjector(binderIndex, parentPeiWithDistance, renderE
366366
componentDirectiveBinding, directiveBindings) {
367367
var protoElementInjector = null;
368368
// Create a protoElementInjector for any element that either has bindings *or* has one
369-
// or more var- defined. Elements with a var- defined need a their own element injector
370-
// so that, when hydrating, $implicit can be set to the element.
369+
// or more var- defined *or* for <template> elements:
370+
// - Elements with a var- defined need a their own element injector
371+
// so that, when hydrating, $implicit can be set to the element.
372+
// - <template> elements need their own ElementInjector so that we can query their TemplateRef
371373
var hasVariables = MapWrapper.size(renderElementBinder.variableBindings) > 0;
372-
if (directiveBindings.length > 0 || hasVariables) {
374+
if (directiveBindings.length > 0 || hasVariables ||
375+
isPresent(renderElementBinder.nestedProtoView)) {
373376
var directiveVariableBindings =
374377
createDirectiveVariableBindings(renderElementBinder, directiveBindings);
375378
protoElementInjector =

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ export class TemplateRef {
2828
/**
2929
* Whether this template has a local variable with the given name
3030
*/
31-
hasLocal(name: string): boolean { return this._getProtoView().protoLocals.has(name); }
31+
hasLocal(name: string): boolean { return this._getProtoView().variableBindings.has(name); }
3232
}

modules/angular2/test/core/compiler/element_injector_spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ class NeedsQueryByVarBindings {
166166
constructor(@Query("one,two") query: QueryList<any>) { this.query = query; }
167167
}
168168

169+
@Injectable()
170+
class NeedsTemplateRefQuery {
171+
query: QueryList<TemplateRef>;
172+
constructor(@Query(TemplateRef) query: QueryList<TemplateRef>) { this.query = query; }
173+
}
174+
169175
@Injectable()
170176
class NeedsElementRef {
171177
elementRef;
@@ -1009,6 +1015,16 @@ export function main() {
10091015
expectDirectives(inj.get(NeedsQuery).query, CountingDirective, [0]);
10101016
})
10111017

1018+
it('should contain PreBuiltObjects on the same injector', () => {
1019+
var preBuiltObjects = new PreBuiltObjects(null, null, null, new TemplateRef(<any>new DummyElementRef()));
1020+
var inj = injector(ListWrapper.concat([
1021+
NeedsTemplateRefQuery
1022+
], extraBindings), null,
1023+
false, preBuiltObjects);
1024+
1025+
expect(inj.get(NeedsTemplateRefQuery).query.first).toBe(preBuiltObjects.templateRef);
1026+
});
1027+
10121028
it('should contain multiple directives from the same injector', () => {
10131029
var inj = injector(ListWrapper.concat([
10141030
NeedsQuery,

modules/angular2/test/core/compiler/query_integration_spec.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ import {
1010
it,
1111
xit,
1212
TestComponentBuilder,
13-
asNativeElements
13+
asNativeElements,
14+
By
1415
} from 'angular2/test_lib';
1516

1617

1718
import {Injectable, Optional} from 'angular2/di';
18-
import {QueryList} from 'angular2/core';
19+
import {QueryList, TemplateRef} from 'angular2/core';
1920
import {Query, ViewQuery, Component, Directive, View} from 'angular2/annotations';
2021

2122
import {NgIf, NgFor} from 'angular2/angular2';
@@ -126,6 +127,24 @@ export function main() {
126127
}));
127128
});
128129

130+
describe('query for TemplateRef', () => {
131+
it('should find TemplateRefs in the light and shadow dom',
132+
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
133+
var template = '<needs-tpl><template var-x="light"></template></needs-tpl>';
134+
tcb.overrideTemplate(MyComp, template)
135+
.createAsync(MyComp)
136+
.then((view) => {
137+
view.detectChanges();
138+
var needsTpl: NeedsTpl = view.componentViewChildren[0].inject(NeedsTpl);
139+
expect(needsTpl.query.first.hasLocal('light')).toBe(true);
140+
expect(needsTpl.viewQuery.first.hasLocal('shadow')).toBe(true);
141+
142+
async.done();
143+
});
144+
}));
145+
146+
});
147+
129148
describe("onChange", () => {
130149
it('should notify query on change',
131150
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
@@ -545,6 +564,18 @@ class NeedsViewQueryOrder {
545564
constructor(@ViewQuery(TextDirective) query: QueryList<TextDirective>) { this.query = query; }
546565
}
547566

567+
@Component({selector: 'needs-tpl'})
568+
@View({template: '<template var-x="shadow"></template>'})
569+
class NeedsTpl {
570+
viewQuery: QueryList<TemplateRef>;
571+
query: QueryList<TemplateRef>;
572+
constructor(@ViewQuery(TemplateRef) viewQuery: QueryList<TemplateRef>,
573+
@Query(TemplateRef) query: QueryList<TemplateRef>) {
574+
this.viewQuery = viewQuery;
575+
this.query = query;
576+
}
577+
}
578+
548579
@Component({selector: 'my-comp'})
549580
@View({
550581
directives: [
@@ -558,6 +589,7 @@ class NeedsViewQueryOrder {
558589
NeedsViewQueryIf,
559590
NeedsViewQueryNestedIf,
560591
NeedsViewQueryOrder,
592+
NeedsTpl,
561593
TextDirective,
562594
InertDirective,
563595
NgIf,

0 commit comments

Comments
 (0)