fix(ivy): allow queries for ng-container without read option (#25617)

PR Close #25617
This commit is contained in:
Pawel Kozlowski 2018-08-22 17:30:27 +02:00 committed by Matias Niemelä
parent b00038c847
commit 8fa099158e
3 changed files with 45 additions and 6 deletions

View File

@ -557,17 +557,21 @@ export const QUERY_READ_ELEMENT_REF =
export const QUERY_READ_FROM_NODE =
(new ReadFromInjectorFn<any>((injector: LInjector, node: LNode, directiveIdx: number) => {
ngDevMode && assertNodeOfPossibleTypes(node, TNodeType.Container, TNodeType.Element);
ngDevMode && assertNodeOfPossibleTypes(
node, TNodeType.Container, TNodeType.Element, TNodeType.ElementContainer);
if (directiveIdx > -1) {
return node.view[DIRECTIVES] ![directiveIdx];
}
if (node.tNode.type === TNodeType.Element) {
if (node.tNode.type === TNodeType.Element || node.tNode.type === TNodeType.ElementContainer) {
return getOrCreateElementRef(injector);
}
if (node.tNode.type === TNodeType.Container) {
return getOrCreateTemplateRef(injector);
}
throw new Error('fail');
if (ngDevMode) {
// should never happen
throw new Error(`Unexpected node type: ${node.tNode.type}`);
}
}) as any as QueryReadType<any>);
/** A ref to a node's native element. */

View File

@ -9,7 +9,7 @@
import {NgForOfContext} from '@angular/common';
import {AttributeMarker, defineComponent, templateRefExtractor} from '../../src/render3/index';
import {bind, template, elementEnd, elementProperty, elementStart, getCurrentView, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, restoreView, text, textBinding, elementContainerStart, elementContainerEnd} from '../../src/render3/instructions';
import {bind, template, elementEnd, elementProperty, elementStart, getCurrentView, interpolation1, interpolation2, interpolation3, interpolationV, listener, load, nextContext, restoreView, text, textBinding, elementContainerStart, elementContainerEnd, reference} from '../../src/render3/instructions';
import {RenderFlags} from '../../src/render3/interfaces/definition';
import {NgForOf, NgIf, NgTemplateOutlet} from './common_with_def';
@ -948,7 +948,7 @@ describe('@angular/common integration', () => {
elementContainerEnd();
}
if (rf & RenderFlags.Update) {
const tplRef = load(1);
const tplRef = reference(1);
elementProperty(2, 'ngTemplateOutlet', bind(myApp.showing ? tplRef : null));
}
},

View File

@ -370,7 +370,7 @@ describe('query', () => {
/**
* <ng-container #foo></ng-container>
* class Cmpt {
* @ViewChildren('foo') query;
* @ViewChildren('foo', {read: ElementRef}) query;
* }
*/
const Cmpt = createComponent(
@ -401,6 +401,41 @@ describe('query', () => {
expect(qList.first.nativeElement).toEqual(elToQuery);
});
it('should query for <ng-container> and read ElementRef without explicit read option', () => {
let elToQuery;
/**
* <ng-container #foo></ng-container>
* class Cmpt {
* @ViewChildren('foo') query;
* }
*/
const Cmpt = createComponent(
'cmpt',
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
elementContainerStart(1, null, ['foo', '']);
elToQuery = loadElement(1).native;
elementContainerEnd();
}
},
3, 0, [], [],
function(rf: RenderFlags, ctx: any) {
if (rf & RenderFlags.Create) {
query(0, ['foo'], true, QUERY_READ_FROM_NODE);
}
if (rf & RenderFlags.Update) {
let tmp: any;
queryRefresh(tmp = load<QueryList<any>>(0)) && (ctx.query = tmp as QueryList<any>);
}
});
const cmptInstance = renderComponent(Cmpt);
const qList = (cmptInstance.query as QueryList<any>);
expect(qList.length).toBe(1);
expect(isElementRef(qList.first)).toBeTruthy();
expect(qList.first.nativeElement).toEqual(elToQuery);
});
/**
* BREAKING CHANGE: this tests asserts different behaviour as compared to Renderer2 when it
* comes to descendants: false option and <ng-container>.