fix(ivy): support static ViewChild queries (#28811)
This commit adds support for the `static: true` flag in `ViewChild` queries. Prior to this commit, all `ViewChild` queries were resolved after change detection ran. This is a problem for backwards compatibility because View Engine also supported "static" queries which would resolve before change detection. Now if users add a `static: true` option, the query will be resolved in creation mode (before change detection runs). For example: ```ts @ViewChild(TemplateRef, {static: true}) template !: TemplateRef; ``` This feature will come in handy for components that need to create components dynamically. PR Close #28811
This commit is contained in:

committed by
Igor Minar

parent
ae16378ee7
commit
a4638d5a81
@ -150,6 +150,7 @@ export interface R3QueryMetadataFacade {
|
||||
predicate: any|string[];
|
||||
descendants: boolean;
|
||||
read: any|null;
|
||||
static: boolean;
|
||||
}
|
||||
|
||||
export interface ParseSourceSpan {
|
||||
|
@ -199,6 +199,7 @@ function convertToR3QueryMetadata(facade: R3QueryMetadataFacade): R3QueryMetadat
|
||||
predicate: Array.isArray(facade.predicate) ? facade.predicate :
|
||||
new WrappedNodeExpr(facade.predicate),
|
||||
read: facade.read ? new WrappedNodeExpr(facade.read) : null,
|
||||
static: facade.static
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -186,6 +186,7 @@ export class Identifiers {
|
||||
|
||||
static queryRefresh: o.ExternalReference = {name: 'ɵqueryRefresh', moduleName: CORE};
|
||||
static viewQuery: o.ExternalReference = {name: 'ɵviewQuery', moduleName: CORE};
|
||||
static staticViewQuery: o.ExternalReference = {name: 'ɵstaticViewQuery', moduleName: CORE};
|
||||
static loadViewQuery: o.ExternalReference = {name: 'ɵloadViewQuery', moduleName: CORE};
|
||||
static contentQuery: o.ExternalReference = {name: 'ɵcontentQuery', moduleName: CORE};
|
||||
static loadContentQuery: o.ExternalReference = {name: 'ɵloadContentQuery', moduleName: CORE};
|
||||
|
@ -229,6 +229,21 @@ export interface R3QueryMetadata {
|
||||
* for a given node is to be returned.
|
||||
*/
|
||||
read: o.Expression|null;
|
||||
|
||||
/**
|
||||
* Whether or not this query should collect only static results.
|
||||
*
|
||||
* If static is true, the query's results will be set on the component after nodes are created,
|
||||
* but before change detection runs. This means that any results that relied upon change detection
|
||||
* to run (e.g. results inside *ngIf or *ngFor views) will not be collected. Query results are
|
||||
* available in the ngOnInit hook.
|
||||
*
|
||||
* If static is false, the query's results will be set on the component after change detection
|
||||
* runs. This means that the query results can contain nodes inside *ngIf or *ngFor views, but
|
||||
* the results will not be available in the ngOnInit hook (only in the ngAfterContentInit for
|
||||
* content hooks and ngAfterViewInit for view hooks).
|
||||
*/
|
||||
static: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -457,6 +457,7 @@ function queriesFromGlobalMetadata(
|
||||
first: query.first,
|
||||
predicate: selectorsFromGlobalMetadata(query.selectors, outputCtx),
|
||||
descendants: query.descendants, read,
|
||||
static: !!query.static
|
||||
};
|
||||
});
|
||||
}
|
||||
@ -490,10 +491,8 @@ function prepareQueryParams(query: R3QueryMetadata, constantPool: ConstantPool):
|
||||
const parameters = [
|
||||
getQueryPredicate(query, constantPool),
|
||||
o.literal(query.descendants),
|
||||
query.read || o.literal(null),
|
||||
];
|
||||
if (query.read) {
|
||||
parameters.push(query.read);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@ -590,9 +589,11 @@ function createViewQueriesFunction(
|
||||
const tempAllocator = temporaryAllocator(updateStatements, TEMPORARY_NAME);
|
||||
|
||||
meta.viewQueries.forEach((query: R3QueryMetadata) => {
|
||||
const queryInstruction = query.static ? R3.staticViewQuery : R3.viewQuery;
|
||||
|
||||
// creation, e.g. r3.viewQuery(somePredicate, true);
|
||||
const queryDefinition =
|
||||
o.importExpr(R3.viewQuery).callFn(prepareQueryParams(query, constantPool));
|
||||
o.importExpr(queryInstruction).callFn(prepareQueryParams(query, constantPool));
|
||||
createStatements.push(queryDefinition.toStmt());
|
||||
|
||||
// update, e.g. (r3.queryRefresh(tmp = r3.loadViewQuery()) && (ctx.someDir = tmp));
|
||||
|
Reference in New Issue
Block a user