fix(core): require 'static' flag on queries in typings (#30639)

This commit makes the static flag on @ViewChild and @ContentChild required.

BREAKING CHANGE:

In Angular version 8, it's required that all @ViewChild and @ContentChild
queries have a 'static' flag specifying whether the query is 'static' or
'dynamic'. The compiler previously sorted queries automatically, but in
8.0 developers are required to explicitly specify which behavior is wanted.
This is a temporary requirement as part of a migration; see
https://angular.io/guide/static-query-migration for more details.

@ViewChildren and @ContentChildren queries are always dynamic, and so are
unaffected.

PR Close #30639
This commit is contained in:
Alex Rickabaugh 2019-05-23 11:31:10 -07:00 committed by Matias Niemelä
parent dc6406e5e8
commit 84dd2679a9
21 changed files with 46 additions and 45 deletions

View File

@ -39,7 +39,7 @@ export class CountdownLocalVarParentComponent { }
}) })
export class CountdownViewChildParentComponent implements AfterViewInit { export class CountdownViewChildParentComponent implements AfterViewInit {
@ViewChild(CountdownTimerComponent) @ViewChild(CountdownTimerComponent, {static: false})
private timerComponent: CountdownTimerComponent; private timerComponent: CountdownTimerComponent;
seconds() { return 0; } seconds() { return 0; }

View File

@ -20,7 +20,7 @@ import { AdComponent } from './ad.component';
export class AdBannerComponent implements OnInit, OnDestroy { export class AdBannerComponent implements OnInit, OnDestroy {
@Input() ads: AdItem[]; @Input() ads: AdItem[];
currentAdIndex = -1; currentAdIndex = -1;
@ViewChild(AdDirective) adHost: AdDirective; @ViewChild(AdDirective, {static: true}) adHost: AdDirective;
interval: any; interval: any;
constructor(private componentFactoryResolver: ComponentFactoryResolver) { } constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

View File

@ -34,7 +34,7 @@ export class AfterContentComponent implements AfterContentChecked, AfterContentI
comment = ''; comment = '';
// Query for a CONTENT child of type `ChildComponent` // Query for a CONTENT child of type `ChildComponent`
@ContentChild(ChildComponent) contentChild: ChildComponent; @ContentChild(ChildComponent, {static: false}) contentChild: ChildComponent;
// #enddocregion hooks // #enddocregion hooks
constructor(private logger: LoggerService) { constructor(private logger: LoggerService) {

View File

@ -35,7 +35,7 @@ export class AfterViewComponent implements AfterViewChecked, AfterViewInit {
private prevHero = ''; private prevHero = '';
// Query for a VIEW child of type `ChildViewComponent` // Query for a VIEW child of type `ChildViewComponent`
@ViewChild(ChildViewComponent) viewChild: ChildViewComponent; @ViewChild(ChildViewComponent, {static: false}) viewChild: ChildViewComponent;
// #enddocregion hooks // #enddocregion hooks
constructor(private logger: LoggerService) { constructor(private logger: LoggerService) {

View File

@ -81,7 +81,7 @@ export class DoCheckParentComponent {
hero: Hero; hero: Hero;
power: string; power: string;
title = 'DoCheck'; title = 'DoCheck';
@ViewChild(DoCheckComponent) childView: DoCheckComponent; @ViewChild(DoCheckComponent, {static: false}) childView: DoCheckComponent;
constructor() { this.reset(); } constructor() { this.reset(); }

View File

@ -55,7 +55,7 @@ export class OnChangesParentComponent {
hero: Hero; hero: Hero;
power: string; power: string;
title = 'OnChanges'; title = 'OnChanges';
@ViewChild(OnChangesComponent) childView: OnChangesComponent; @ViewChild(OnChangesComponent, {static: false}) childView: OnChangesComponent;
constructor() { constructor() {
this.reset(); this.reset();

View File

@ -13,7 +13,7 @@ import { Hero } from './hero';
}) })
export class HeroFormComponent { export class HeroFormComponent {
@Input() hero: Hero; @Input() hero: Hero;
@ViewChild('heroForm') form: NgForm; @ViewChild('heroForm', {static: false}) form: NgForm;
private _submitMessage = ''; private _submitMessage = '';

View File

@ -6,7 +6,7 @@ import { Component, AfterViewInit, ViewChild } from '@angular/core';
}) })
export class CanvasComponent implements AfterViewInit { export class CanvasComponent implements AfterViewInit {
blobSize: number; blobSize: number;
@ViewChild('sampleCanvas') sampleCanvas; @ViewChild('sampleCanvas', {static: false}) sampleCanvas;
constructor() { } constructor() { }

View File

@ -96,5 +96,5 @@ class HostComponent {
path = 'code-path'; path = 'code-path';
hidecopy: boolean | string = false; hidecopy: boolean | string = false;
@ViewChild(CodeExampleComponent) codeExampleComponent: CodeExampleComponent; @ViewChild(CodeExampleComponent, {static: true}) codeExampleComponent: CodeExampleComponent;
} }

View File

@ -92,5 +92,5 @@ describe('CodeTabsComponent', () => {
` `
}) })
class HostComponent { class HostComponent {
@ViewChild(CodeTabsComponent) codeTabsComponent: CodeTabsComponent; @ViewChild(CodeTabsComponent, {static: true}) codeTabsComponent: CodeTabsComponent;
} }

View File

@ -284,7 +284,7 @@ class HostComponent implements AfterViewInit {
region: string; region: string;
header: string; header: string;
@ViewChild(CodeComponent) codeComponent: CodeComponent; @ViewChild(CodeComponent, {static: false}) codeComponent: CodeComponent;
ngAfterViewInit() { ngAfterViewInit() {
this.setCode(oneLineCode); this.setCode(oneLineCode);

View File

@ -37,7 +37,7 @@ export class TestDocViewerComponent extends DocViewerComponent {
}) })
export class TestParentComponent { export class TestParentComponent {
currentDoc?: DocumentContents|null; currentDoc?: DocumentContents|null;
@ViewChild(DocViewerComponent) docViewer: DocViewerComponent; @ViewChild(DocViewerComponent, {static: true}) docViewer: DocViewerComponent;
} }
// Mock services. // Mock services.

View File

@ -10,18 +10,16 @@ declare var System: any;
`, `,
}) })
export class AppComponent implements AfterViewInit { export class AppComponent implements AfterViewInit {
@ViewChild('vc', {read: ViewContainerRef}) container: ViewContainerRef; @ViewChild('vc', {read: ViewContainerRef, static: false}) container: ViewContainerRef;
constructor(private compiler: Compiler) { constructor(private compiler: Compiler) {}
}
ngAfterViewInit() { ngAfterViewInit() {
System.import('./dist/lazy.bundle.js').then((module: any) => { System.import('./dist/lazy.bundle.js').then((module: any) => {
this.compiler.compileModuleAndAllComponentsAsync(module.LazyModule) this.compiler.compileModuleAndAllComponentsAsync(module.LazyModule).then((compiled) => {
.then((compiled) => { const factory = compiled.componentFactories[0];
const factory = compiled.componentFactories[0]; this.container.createComponent(factory);
this.container.createComponent(factory); });
});
}); });
} }
} }

View File

@ -15,7 +15,7 @@ export class CompForChildQuery {
@Component( @Component(
{selector: 'comp-with-child-query', template: '<comp-for-child-query></comp-for-child-query>'}) {selector: 'comp-with-child-query', template: '<comp-for-child-query></comp-for-child-query>'})
export class CompWithChildQuery { export class CompWithChildQuery {
@ViewChild(CompForChildQuery) child: CompForChildQuery; @ViewChild(CompForChildQuery, {static: true}) child: CompForChildQuery;
@ViewChildren(CompForChildQuery) children: QueryList<CompForChildQuery>; @ViewChildren(CompForChildQuery) children: QueryList<CompForChildQuery>;
} }

View File

@ -29,7 +29,7 @@ export interface Query {
read: any; read: any;
isViewQuery: boolean; isViewQuery: boolean;
selector: any; selector: any;
static?: boolean; static: boolean;
} }
export const createContentChildren = makeMetadataFactory<Query>( export const createContentChildren = makeMetadataFactory<Query>(

View File

@ -102,7 +102,7 @@ export interface Query {
read: any; read: any;
isViewQuery: boolean; isViewQuery: boolean;
selector: any; selector: any;
static?: boolean; static: boolean;
} }
/** /**
@ -218,8 +218,8 @@ export interface ContentChildDecorator {
* *
* @Annotation * @Annotation
*/ */
(selector: Type<any>|Function|string, opts?: {read?: any, static?: boolean}): any; (selector: Type<any>|Function|string, opts: {read?: any, static: boolean}): any;
new (selector: Type<any>|Function|string, opts?: {read?: any, static?: boolean}): ContentChild; new (selector: Type<any>|Function|string, opts: {read?: any, static: boolean}): ContentChild;
} }
/** /**
@ -350,8 +350,8 @@ export interface ViewChildDecorator {
* *
* @Annotation * @Annotation
*/ */
(selector: Type<any>|Function|string, opts?: {read?: any, static?: boolean}): any; (selector: Type<any>|Function|string, opts: {read?: any, static: boolean}): any;
new (selector: Type<any>|Function|string, opts?: {read?: any, static?: boolean}): ViewChild; new (selector: Type<any>|Function|string, opts: {read?: any, static: boolean}): ViewChild;
} }
/** /**

View File

@ -52,7 +52,8 @@ describe('jit directive helper functions', () => {
descendants: false, descendants: false,
first: false, first: false,
isViewQuery: false, isViewQuery: false,
read: undefined read: undefined,
static: false,
})).toEqual({ })).toEqual({
propertyName: 'propName', propertyName: 'propName',
predicate: ['localRef'], predicate: ['localRef'],
@ -69,7 +70,8 @@ describe('jit directive helper functions', () => {
descendants: true, descendants: true,
first: true, first: true,
isViewQuery: true, isViewQuery: true,
read: undefined read: undefined,
static: false,
})).toEqual({ })).toEqual({
propertyName: 'propName', propertyName: 'propName',
predicate: ['foo', 'bar', 'baz'], predicate: ['foo', 'bar', 'baz'],

View File

@ -168,7 +168,7 @@ import {el} from '../../testing/src/browser_util';
}) })
class Cmp { class Cmp {
exp: any; exp: any;
@ViewChild('elm') public element: any; @ViewChild('elm', {static: false}) public element: any;
} }
TestBed.configureTestingModule({ TestBed.configureTestingModule({
@ -213,11 +213,11 @@ import {el} from '../../testing/src/browser_util';
exp2: any = true; exp2: any = true;
exp3: any = true; exp3: any = true;
@ViewChild('elm1') public elm1: any; @ViewChild('elm1', {static: false}) public elm1: any;
@ViewChild('elm2') public elm2: any; @ViewChild('elm2', {static: false}) public elm2: any;
@ViewChild('elm3') public elm3: any; @ViewChild('elm3', {static: false}) public elm3: any;
} }
TestBed.configureTestingModule({ TestBed.configureTestingModule({

View File

@ -51,7 +51,7 @@ import {el} from '../../testing/src/browser_util';
template: '...', template: '...',
}) })
class Cmp { class Cmp {
@ViewChild('target') public target: any; @ViewChild('target', {static: false}) public target: any;
constructor(public builder: AnimationBuilder) {} constructor(public builder: AnimationBuilder) {}

View File

@ -73,9 +73,10 @@ describe('Integration', () => {
}) })
class ComponentWithRouterLink { class ComponentWithRouterLink {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
@ViewChild(TemplateRef) templateRef !: TemplateRef<any>; @ViewChild(TemplateRef, {static: true}) templateRef !: TemplateRef<any>;
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
@ViewChild('container', {read: ViewContainerRef}) container !: ViewContainerRef; @ViewChild('container', {read: ViewContainerRef, static: true})
container !: ViewContainerRef;
addLink() { addLink() {
this.container.createEmbeddedView(this.templateRef, {$implicit: '/simple'}); this.container.createEmbeddedView(this.templateRef, {$implicit: '/simple'});

View File

@ -168,13 +168,13 @@ export interface ConstructorSansProvider {
export declare type ContentChild = Query; export declare type ContentChild = Query;
export interface ContentChildDecorator { export interface ContentChildDecorator {
(selector: Type<any> | Function | string, opts?: { (selector: Type<any> | Function | string, opts: {
read?: any; read?: any;
static?: boolean; static: boolean;
}): any; }): any;
new (selector: Type<any> | Function | string, opts?: { new (selector: Type<any> | Function | string, opts: {
read?: any; read?: any;
static?: boolean; static: boolean;
}): ContentChild; }): ContentChild;
} }
@ -1104,7 +1104,7 @@ export interface Query {
isViewQuery: boolean; isViewQuery: boolean;
read: any; read: any;
selector: any; selector: any;
static?: boolean; static: boolean;
} }
export declare abstract class Query { export declare abstract class Query {
@ -1382,13 +1382,13 @@ export declare const VERSION: Version;
export declare type ViewChild = Query; export declare type ViewChild = Query;
export interface ViewChildDecorator { export interface ViewChildDecorator {
(selector: Type<any> | Function | string, opts?: { (selector: Type<any> | Function | string, opts: {
read?: any; read?: any;
static?: boolean; static: boolean;
}): any; }): any;
new (selector: Type<any> | Function | string, opts?: { new (selector: Type<any> | Function | string, opts: {
read?: any; read?: any;
static?: boolean; static: boolean;
}): ViewChild; }): ViewChild;
} }