feat(ivy): compile queries in ngtsc (#24862)

This commit adds support for @ContentChild[ren] and @ViewChild[ren] in
ngtsc. Previously queries were ignored.

PR Close #24862
This commit is contained in:
Alex Rickabaugh
2018-07-18 09:32:36 -07:00
committed by Victor Berchet
parent 6eb6ac7c12
commit 76f8f78920
4 changed files with 211 additions and 20 deletions

View File

@ -6,7 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
type FnWithArg<T> = (arg?: any) => T;
interface FnWithArg<T> {
(...args: any[]): T;
new (...args: any[]): T;
}
function callableClassDecorator(): FnWithArg<(clazz: any) => any> {
return null !;
@ -16,6 +19,10 @@ function callableParamDecorator(): FnWithArg<(a: any, b: any, c: any) => void> {
return null !;
}
function callablePropDecorator(): FnWithArg<(a: any, b: any) => any> {
return null !;
}
export const Component = callableClassDecorator();
export const Directive = callableClassDecorator();
export const Injectable = callableClassDecorator();
@ -27,6 +34,12 @@ export const Inject = callableParamDecorator();
export const Self = callableParamDecorator();
export const SkipSelf = callableParamDecorator();
export const Optional = callableParamDecorator();
export const ContentChild = callablePropDecorator();
export const ContentChildren = callablePropDecorator();
export const ViewChild = callablePropDecorator();
export const ViewChildren = callablePropDecorator();
export type ModuleWithProviders<T> = any;
export class ChangeDetectorRef {}

View File

@ -412,4 +412,36 @@ describe('ngtsc behavioral tests', () => {
.toContain(
`factory: function FooCmp_Factory() { return new FooCmp(i0.ɵinjectAttribute("test"), i0.ɵinjectChangeDetectorRef(), i0.ɵinjectElementRef(), i0.ɵdirectiveInject(i0.INJECTOR), i0.ɵinjectTemplateRef(), i0.ɵinjectViewContainerRef()); }`);
});
it('should generate queries for components', () => {
writeConfig();
write(`test.ts`, `
import {Component, ContentChild, ContentChildren, TemplateRef, ViewChild} from '@angular/core';
@Component({
selector: 'test',
template: '<div #foo></div>',
queries: {
'mview': new ViewChild('test1'),
'mcontent': new ContentChild('test2'),
}
})
class FooCmp {
@ContentChild('bar', {read: TemplateRef}) child: any;
@ContentChildren(TemplateRef) children: any;
get aview(): any { return null; }
@ViewChild('accessor') set aview(value: any) {}
}
`);
const exitCode = main(['-p', basePath], errorSpy);
expect(errorSpy).not.toHaveBeenCalled();
expect(exitCode).toBe(0);
const jsContents = getContents('test.js');
expect(jsContents).toContain(`i0.ɵQ(null, ["bar"], true, TemplateRef)`);
expect(jsContents).toContain(`i0.ɵQ(null, TemplateRef, false)`);
expect(jsContents).toContain(`i0.ɵQ(null, ["test2"], true)`);
expect(jsContents).toContain(`i0.ɵQ(0, ["accessor"], true)`);
expect(jsContents).toContain(`i0.ɵQ(1, ["test1"], true)`);
});
});