feat(core): introduce template context

BREAKING CHANGE:
- Before, a `EmbeddedViewRef` used to have methods for 
  setting variables. Now, a user has to pass in a context
  object that represents all variables when an `EmbeddedViewRef`
  should be created.
- `ViewContainerRef.createEmbeddedViewRef` now takes
   a context object as 2nd argument.
- `EmbeddedViewRef.setLocal` and `getLocal` have been removed.
  Use `EmbeddedViewRef.context` to access the context.
- `DebugNode.locals` has been removed. Use the new methods `DebugElement.references`
  to get the references that are present on this element,
  or `DebugElement.context` to get the context of the `EmbeddedViewRef` or the component to which the element belongs.

Closes #8321
This commit is contained in:
Tobias Bosch
2016-04-28 14:00:31 -07:00
parent 96ae348648
commit cacdead96d
28 changed files with 277 additions and 246 deletions

View File

@ -1351,11 +1351,14 @@ class OrderCheckDirective2 {
constructor(public log: DirectiveLog, _check1: OrderCheckDirective1) {}
}
class TestLocalsContext {
constructor(public someLocal: string) {}
}
@Directive({selector: '[testLocals]'})
class TestLocals {
constructor(templateRef: TemplateRef, vcRef: ViewContainerRef) {
var viewRef = vcRef.createEmbeddedView(templateRef);
viewRef.setLocal('someLocal', 'someLocalValue');
constructor(templateRef: TemplateRef<TestLocalsContext>, vcRef: ViewContainerRef) {
vcRef.createEmbeddedView(templateRef, new TestLocalsContext('someLocalValue'));
}
}

View File

@ -348,7 +348,7 @@ function declareTests(isJit: boolean) {
fixture.debugElement.componentInstance.ctxProp = 'a';
fixture.detectChanges();
var dir = fixture.debugElement.children[0].getLocal('dir');
var dir = fixture.debugElement.children[0].references['dir'];
expect(dir.dirProp).toEqual('aa');
async.done();
});
@ -473,7 +473,7 @@ function declareTests(isJit: boolean) {
tcb.overrideView(
MyComp, new ViewMetadata({
template:
'<template some-viewport let-greeting="some-tmpl"><copy-me>{{greeting}}</copy-me></template>',
'<template some-viewport let-greeting="someTmpl"><copy-me>{{greeting}}</copy-me></template>',
directives: [SomeViewport]
}))
@ -509,7 +509,7 @@ function declareTests(isJit: boolean) {
tcb.overrideView(
MyComp, new ViewMetadata({
template:
'<copy-me template="some-viewport: let greeting=some-tmpl">{{greeting}}</copy-me>',
'<copy-me template="some-viewport: let greeting=someTmpl">{{greeting}}</copy-me>',
directives: [SomeViewport]
}))
@ -558,7 +558,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
expect(fixture.debugElement.children[0].children[0].getLocal('alice'))
expect(fixture.debugElement.children[0].children[0].references['alice'])
.toBeAnInstanceOf(ChildComp);
async.done();
@ -574,7 +574,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
expect(fixture.debugElement.children[0].children[0].getLocal('localdir'))
expect(fixture.debugElement.children[0].children[0].references['localdir'])
.toBeAnInstanceOf(ExportDir);
async.done();
@ -613,11 +613,13 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
var childCmp = fixture.debugElement.children[0].children[0];
var pEl = fixture.debugElement.children[0];
expect(childCmp.getLocal('alice')).toBeAnInstanceOf(ChildComp);
expect(childCmp.getLocal('bob')).toBeAnInstanceOf(ChildComp);
expect(childCmp.getLocal('alice')).not.toBe(childCmp.getLocal('bob'));
var alice = pEl.children[0].references['alice'];
var bob = pEl.children[1].references['bob'];
expect(alice).toBeAnInstanceOf(ChildComp);
expect(bob).toBeAnInstanceOf(ChildComp);
expect(alice).not.toBe(bob);
async.done();
})}));
@ -633,7 +635,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
expect(fixture.debugElement.children[0].getLocal('alice'))
expect(fixture.debugElement.children[0].references['alice'])
.toBeAnInstanceOf(ChildComp);
async.done();
@ -650,7 +652,7 @@ function declareTests(isJit: boolean) {
.then((fixture) => {
var value =
fixture.debugElement.children[0].children[0].getLocal('alice');
fixture.debugElement.children[0].children[0].references['alice'];
expect(value).not.toBe(null);
expect(value.tagName.toLowerCase()).toEqual('div');
@ -666,7 +668,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
var value = fixture.debugElement.childNodes[0].getLocal('alice');
var value = fixture.debugElement.childNodes[0].references['alice'];
expect(value).toBeAnInstanceOf(TemplateRef_);
async.done();
@ -682,7 +684,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
expect(fixture.debugElement.children[0].children[0].getLocal('superAlice'))
expect(fixture.debugElement.children[0].children[0].references['superAlice'])
.toBeAnInstanceOf(ChildComp);
async.done();
@ -727,7 +729,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
var cmp = fixture.debugElement.children[0].getLocal('cmp');
var cmp = fixture.debugElement.children[0].references['cmp'];
fixture.detectChanges();
expect(cmp.numberOfChecks).toEqual(1);
@ -753,7 +755,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
var cmp = fixture.debugElement.children[0].getLocal('cmp');
var cmp = fixture.debugElement.children[0].references['cmp'];
fixture.debugElement.componentInstance.ctxProp = "one";
fixture.detectChanges();
@ -800,7 +802,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
var cmp = fixture.debugElement.children[0].getLocal('cmp');
var cmp = fixture.debugElement.children[0].references['cmp'];
fixture.debugElement.componentInstance.ctxProp = "one";
fixture.detectChanges();
@ -826,7 +828,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
var cmp = fixture.debugElement.children[0].getLocal('cmp');
var cmp = fixture.debugElement.children[0].references['cmp'];
fixture.debugElement.componentInstance.ctxProp = "one";
fixture.detectChanges();
@ -852,7 +854,7 @@ function declareTests(isJit: boolean) {
tcb.createAsync(MyComp).then(root => { fixture = root; });
tick();
var cmp: PushCmpWithAsyncPipe = fixture.debugElement.children[0].getLocal('cmp');
var cmp: PushCmpWithAsyncPipe = fixture.debugElement.children[0].references['cmp'];
fixture.detectChanges();
expect(cmp.numberOfChecks).toEqual(1);
@ -871,25 +873,28 @@ function declareTests(isJit: boolean) {
it('should create a component that injects an @Host',
inject([TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async) => {
tcb.overrideView(MyComp, new ViewMetadata({
template: `
(tcb: TestComponentBuilder,
async) => {tcb.overrideView(MyComp, new ViewMetadata({
template: `
<some-directive>
<p>
<cmp-with-host #child></cmp-with-host>
</p>
</some-directive>`,
directives: [SomeDirective, CompWithHost]
}))
directives: [SomeDirective, CompWithHost]
}))
.createAsync(MyComp)
.then((fixture) => {
.createAsync(MyComp)
.then((fixture) => {
var childComponent = fixture.debugElement.children[0].getLocal('child');
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
var childComponent = fixture.debugElement.children[0]
.children[0]
.children[0]
.references['child'];
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
async.done();
})}));
async.done();
})}));
it('should create a component that injects an @Host through viewcontainer directive',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
@ -909,7 +914,7 @@ function declareTests(isJit: boolean) {
var tc = fixture.debugElement.children[0].children[0].children[0];
var childComponent = tc.getLocal('child');
var childComponent = tc.references['child'];
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
async.done();
@ -1235,7 +1240,7 @@ function declareTests(isJit: boolean) {
}))
.createAsync(MyComp)
.then((fixture) => {
var comp = fixture.debugElement.children[0].getLocal("consuming");
var comp = fixture.debugElement.children[0].children[0].references["consuming"];
expect(comp.injectable).toBeAnInstanceOf(InjectableService);
async.done();
@ -1253,7 +1258,7 @@ function declareTests(isJit: boolean) {
}))
.createAsync(DirectiveProvidingInjectableInView)
.then((fixture) => {
var comp = fixture.debugElement.children[0].getLocal("consuming");
var comp = fixture.debugElement.children[0].references["consuming"];
expect(comp.injectable).toBeAnInstanceOf(InjectableService);
async.done();
@ -1283,7 +1288,7 @@ function declareTests(isJit: boolean) {
.createAsync(MyComp)
.then((fixture) => {
var comp = fixture.debugElement.children[0].getLocal("dir");
var comp = fixture.debugElement.children[0].children[0].references["dir"];
expect(comp.directive.injectable).toBeAnInstanceOf(InjectableService);
async.done();
@ -1341,7 +1346,7 @@ function declareTests(isJit: boolean) {
}))
.createAsync(MyComp)
.then((fixture) => {
var providing = fixture.debugElement.children[0].getLocal("providing");
var providing = fixture.debugElement.children[0].references["providing"];
expect(providing.created).toBe(false);
fixture.debugElement.componentInstance.ctxBoolProp = true;
@ -1444,7 +1449,7 @@ function declareTests(isJit: boolean) {
expect((<Injector>c.injector).get).toBeTruthy();
expect(c.source).toContain(":0:7");
expect(c.context).toBe(fixture.debugElement.componentInstance);
expect(c.locals["local"]).toBeDefined();
expect(c.references["local"]).toBeDefined();
}
async.done();
@ -1498,7 +1503,7 @@ function declareTests(isJit: boolean) {
expect(DOM.nodeName(c.componentRenderElement).toUpperCase()).toEqual("DIV");
expect((<Injector>c.injector).get).toBeTruthy();
expect(c.context).toBe(fixture.debugElement.componentInstance);
expect(c.locals["local"]).toBeDefined();
expect(c.references["local"]).toBeDefined();
}
})));
}
@ -2137,12 +2142,16 @@ class ChildComp2 {
}
}
class SomeViewportContext {
constructor(public someTmpl: string) {}
}
@Directive({selector: '[some-viewport]'})
@Injectable()
class SomeViewport {
constructor(container: ViewContainerRef, templateRef: TemplateRef) {
container.createEmbeddedView(templateRef).setLocal('some-tmpl', 'hello');
container.createEmbeddedView(templateRef).setLocal('some-tmpl', 'again');
constructor(container: ViewContainerRef, templateRef: TemplateRef<SomeViewportContext>) {
container.createEmbeddedView(templateRef, new SomeViewportContext('hello'));
container.createEmbeddedView(templateRef, new SomeViewportContext('again'));
}
}
@ -2277,11 +2286,15 @@ class NeedsPublicApi {
constructor(@Host() api: PublicApi) { expect(api instanceof PrivateImpl).toBe(true); }
}
class ToolbarContext {
constructor(public toolbarProp: string) {}
}
@Directive({selector: '[toolbarpart]'})
@Injectable()
class ToolbarPart {
templateRef: TemplateRef;
constructor(templateRef: TemplateRef) { this.templateRef = templateRef; }
templateRef: TemplateRef<ToolbarContext>;
constructor(templateRef: TemplateRef<ToolbarContext>) { this.templateRef = templateRef; }
}
@Directive({selector: '[toolbarVc]', inputs: ['toolbarVc']})
@ -2291,8 +2304,7 @@ class ToolbarViewContainer {
constructor(vc: ViewContainerRef) { this.vc = vc; }
set toolbarVc(part: ToolbarPart) {
var view = this.vc.createEmbeddedView(part.templateRef, 0);
view.setLocal('toolbarProp', 'From toolbar');
this.vc.createEmbeddedView(part.templateRef, new ToolbarContext('From toolbar'), 0);
}
}
@ -2453,9 +2465,9 @@ class ChildConsumingEventBus {
@Directive({selector: '[someImpvp]', inputs: ['someImpvp']})
@Injectable()
class SomeImperativeViewport {
view: EmbeddedViewRef;
view: EmbeddedViewRef<Object>;
anchor;
constructor(public vc: ViewContainerRef, public templateRef: TemplateRef,
constructor(public vc: ViewContainerRef, public templateRef: TemplateRef<Object>,
@Inject(ANCHOR_ELEMENT) anchor) {
this.view = null;
this.anchor = anchor;

View File

@ -691,15 +691,15 @@ class MultipleContentTagsComponent {
@Directive({selector: '[manual]'})
class ManualViewportDirective {
constructor(public vc: ViewContainerRef, public templateRef: TemplateRef) {}
show() { this.vc.createEmbeddedView(this.templateRef, 0); }
constructor(public vc: ViewContainerRef, public templateRef: TemplateRef<Object>) {}
show() { this.vc.createEmbeddedView(this.templateRef); }
hide() { this.vc.clear(); }
}
@Directive({selector: '[project]'})
class ProjectDirective {
constructor(public vc: ViewContainerRef) {}
show(templateRef: TemplateRef) { this.vc.createEmbeddedView(templateRef, 0); }
show(templateRef: TemplateRef<Object>) { this.vc.createEmbeddedView(templateRef); }
hide() { this.vc.clear(); }
}

View File

@ -68,7 +68,7 @@ export function main() {
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.children[0].references['q'];
view.detectChanges();
@ -90,7 +90,7 @@ export function main() {
view.debugElement.componentInstance.shouldShow = true;
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.children[0].references['q'];
expect(q.log).toEqual([["setter", "foo"], ["init", "foo"], ["check", "foo"]]);
@ -117,7 +117,7 @@ export function main() {
.createAsync(MyComp)
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.children[0].references['q'];
expect(q.log).toEqual([["setter", "foo"], ["init", "foo"], ["check", "foo"]]);
@ -146,7 +146,7 @@ export function main() {
.createAsync(MyComp)
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.children[0].references['q'];
expect(q.log).toEqual([["setter", "foo"], ["init", "foo"], ["check", "foo"]]);
@ -268,17 +268,17 @@ export function main() {
describe('query for TemplateRef', () => {
it('should find TemplateRefs in the light and shadow dom',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template = '<needs-tpl><template let-x="light"></template></needs-tpl>';
var template = '<needs-tpl><template><div>light</div></template></needs-tpl>';
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
view.detectChanges();
var needsTpl: NeedsTpl = view.debugElement.children[0].inject(NeedsTpl);
expect(needsTpl.vc.createEmbeddedView(needsTpl.query.first).hasLocal('light'))
.toBe(true);
expect(needsTpl.vc.createEmbeddedView(needsTpl.viewQuery.first).hasLocal('shadow'))
.toBe(true);
expect(needsTpl.vc.createEmbeddedView(needsTpl.query.first).rootNodes[0])
.toHaveText('light');
expect(needsTpl.vc.createEmbeddedView(needsTpl.viewQuery.first).rootNodes[0])
.toHaveText('shadow');
async.done();
});
@ -287,18 +287,18 @@ export function main() {
it('should find named TemplateRefs',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
var template =
'<needs-named-tpl><template let-x="light" #tpl></template></needs-named-tpl>';
'<needs-named-tpl><template #tpl><div>light</div></template></needs-named-tpl>';
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
view.detectChanges();
var needsTpl: NeedsNamedTpl = view.debugElement.children[0].inject(NeedsNamedTpl);
expect(needsTpl.vc.createEmbeddedView(needsTpl.contentTpl).hasLocal('light'))
.toBe(true);
expect(needsTpl.vc.createEmbeddedView(needsTpl.viewTpl).hasLocal('shadow'))
.toBe(true);
expect(needsTpl.vc.createEmbeddedView(needsTpl.contentTpl).rootNodes[0])
.toHaveText('light');
expect(needsTpl.vc.createEmbeddedView(needsTpl.viewTpl).rootNodes[0])
.toHaveText('shadow')
async.done();
async.done();
});
}));
});
@ -407,7 +407,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.children[0].references["q"];
view.detectChanges();
ObservableWrapper.subscribe(q.query.changes, (_) => {
@ -432,8 +432,8 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q1 = view.debugElement.children[0].getLocal("q1");
var q2 = view.debugElement.children[0].getLocal("q2");
var q1 = view.debugElement.children[0].references["q1"];
var q2 = view.debugElement.children[0].children[0].references["q2"];
var firedQ2 = false;
@ -457,7 +457,7 @@ export function main() {
view.debugElement.componentInstance.shouldShow = true;
view.detectChanges();
var q: NeedsQuery = view.debugElement.children[0].getLocal('q');
var q: NeedsQuery = view.debugElement.children[0].references['q'];
expect(q.query.length).toEqual(1);
@ -467,7 +467,7 @@ export function main() {
view.debugElement.componentInstance.shouldShow = true;
view.detectChanges();
var q2: NeedsQuery = view.debugElement.children[0].getLocal('q');
var q2: NeedsQuery = view.debugElement.children[0].references['q'];
expect(q2.query.length).toEqual(1);
@ -487,7 +487,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.children[0].references["q"];
view.debugElement.componentInstance.list = ['1d', '2d'];
@ -510,7 +510,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.children[0].references["q"];
view.detectChanges();
expect(q.query.first.text).toEqual("one");
@ -530,7 +530,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.children[0].references["q"];
view.debugElement.componentInstance.list = ['1d', '2d'];
@ -557,7 +557,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q = view.debugElement.children[0].getLocal("q");
var q = view.debugElement.children[0].references["q"];
view.debugElement.componentInstance.list = ['1d', '2d'];
@ -594,7 +594,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryByLabel = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryByLabel = view.debugElement.children[0].references["q"];
view.detectChanges();
expect(q.query.first.nativeElement).toHaveText("text");
@ -612,7 +612,7 @@ export function main() {
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.children[0].references['q'];
view.detectChanges();
@ -633,7 +633,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQuery = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQuery = view.debugElement.children[0].references["q"];
view.detectChanges();
@ -650,7 +650,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQuery = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQuery = view.debugElement.children[0].references["q"];
view.detectChanges();
@ -667,7 +667,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryIf = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryIf = view.debugElement.children[0].references["q"];
view.detectChanges();
@ -690,7 +690,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryNestedIf = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryNestedIf = view.debugElement.children[0].references["q"];
view.detectChanges();
@ -715,7 +715,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryOrder = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryOrder = view.debugElement.children[0].references["q"];
view.detectChanges();
@ -738,7 +738,8 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryOrderWithParent = view.debugElement.children[0].getLocal("q");
var q: NeedsViewQueryOrderWithParent =
view.debugElement.children[0].references["q"];
view.detectChanges();
@ -761,7 +762,7 @@ export function main() {
tcb.overrideTemplate(MyComp, template)
.createAsync(MyComp)
.then((view) => {
var q: NeedsViewQueryOrder = view.debugElement.children[0].getLocal('q');
var q: NeedsViewQueryOrder = view.debugElement.children[0].references['q'];
// no significance to 50, just a reasonably large cycle.
for (var i = 0; i < 50; i++) {
@ -785,7 +786,7 @@ export function main() {
.then((view) => {
view.detectChanges();
var q = view.debugElement.children[0].getLocal('q');
var q = view.debugElement.children[0].references['q'];
expect(q.query1).toBeDefined();
expect(q.query2).toBeDefined();
expect(q.query3).toBeDefined();
@ -897,7 +898,7 @@ class NeedsFourQueries {
@Component({
selector: 'needs-query-desc',
directives: [NgFor],
template: '<div *ngFor="let dir of query">{{dir.text}}|</div>'
template: '<ng-content></ng-content><div *ngFor="let dir of query">{{dir.text}}|</div>'
})
@Injectable()
class NeedsQueryDesc {
@ -1024,21 +1025,22 @@ class NeedsViewQueryOrderWithParent {
}
}
@Component({selector: 'needs-tpl', template: '<template let-x="shadow"></template>'})
@Component({selector: 'needs-tpl', template: '<template><div>shadow</div></template>'})
class NeedsTpl {
viewQuery: QueryList<TemplateRef>;
query: QueryList<TemplateRef>;
constructor(@ViewQuery(TemplateRef) viewQuery: QueryList<TemplateRef>,
@Query(TemplateRef) query: QueryList<TemplateRef>, public vc: ViewContainerRef) {
viewQuery: QueryList<TemplateRef<Object>>;
query: QueryList<TemplateRef<Object>>;
constructor(@ViewQuery(TemplateRef) viewQuery: QueryList<TemplateRef<Object>>,
@Query(TemplateRef) query: QueryList<TemplateRef<Object>>,
public vc: ViewContainerRef) {
this.viewQuery = viewQuery;
this.query = query;
}
}
@Component({selector: 'needs-named-tpl', template: '<template #tpl let-x="shadow"></template>'})
@Component({selector: 'needs-named-tpl', template: '<template #tpl><div>shadow</div></template>'})
class NeedsNamedTpl {
@ViewChild('tpl') viewTpl: TemplateRef;
@ContentChild('tpl') contentTpl: TemplateRef;
@ViewChild('tpl') viewTpl: TemplateRef<Object>;
@ContentChild('tpl') contentTpl: TemplateRef<Object>;
constructor(public vc: ViewContainerRef) {}
}
@ -1078,7 +1080,7 @@ class NeedsViewChildWithRead {
class NeedsViewContainerWithRead {
@ViewChild('q', {read: ViewContainerRef}) vc: ViewContainerRef;
@ViewChild('nonExisting', {read: ViewContainerRef}) nonExistingVar: ViewContainerRef;
@ContentChild(TemplateRef) template: TemplateRef;
@ContentChild(TemplateRef) template: TemplateRef<Object>;
createView() { this.vc.createEmbeddedView(this.template); }
}

View File

@ -206,13 +206,13 @@ class NeedsViewContainerRef {
@Directive({selector: '[needsTemplateRef]'})
class NeedsTemplateRef {
templateRef;
constructor(ref: TemplateRef) { this.templateRef = ref; }
constructor(ref: TemplateRef<Object>) { this.templateRef = ref; }
}
@Directive({selector: '[optionallyNeedsTemplateRef]'})
class OptionallyNeedsTemplateRef {
templateRef;
constructor(@Optional() ref: TemplateRef) { this.templateRef = ref; }
constructor(@Optional() ref: TemplateRef<Object>) { this.templateRef = ref; }
}
@Directive({selector: '[directiveNeedsChangeDetectorRef]'})