Queries Migration
To have a unifying experience with Signals, Angular 17 introduces the Signal-based Queries to replace the Decorator-based ones:
@ContentChild->contentChild()@ContentChildren->contentChildren()@ViewChild->viewChild()@ViewChildren->viewChildren()
How it works?
Section titled “How it works?”The moment you run the schematics, it will look for all the decorators that have queries and convert them to signal queries.
- It will keep the same name for the queries.
- It will keep the same types and default values.
- It will also convert the query references to signal query references.
- It will update the components template to use the new signal queries (by adding
()to the query references, it may cause some errors when it comes to type narrowing of signal function calls, but that’s something that you can fix, by adding!to the signal function calls that are inside@ifblocks). - It won’t convert setter queries.
- It will remove the
@ContentChild,@ContentChildren,@ViewChild, and@ViewChildrendecorators if they are no longer used.
Example
Section titled “Example”Before running the schematics:
import { Component, ContentChild, ContentChildren, ViewChild, ViewChildren,} from '@angular/core';
@Component()export class AppComponent { @ContentChild('my-content-child') myContentChild: ElementRef<HTMLImageElement>; @ContentChildren('my-content-children') myContentChildren: QueryList< ElementRef<HTMLImageElement> >; @ViewChild('my-view-child') myViewChild: ElementRef<HTMLImageElement>; @ViewChildren('my-view-children') myViewChildren: QueryList< ElementRef<HTMLImageElement> >;
@ViewChild('my-input') set myInput(el: ElementRef<HTMLInputElement>) { el.nativeElement.focus(); }}After running the schematics:
import { Component, contentChild, contentChildren, viewChild, viewChildren,} from '@angular/core';
@Component()export class AppComponent { myContentChild = contentChild<ElementRef<HTMLImageElement>>('my-content-child'); // ^? Signal<ElementRef<HTMLImageElement>> myContentChildren = contentChildren<ElementRef<HTMLImageElement>>( 'my-content-children', ); // ^? Signal<ReadonlyArray<ElementRef<HTMLImageElement>>> myViewChild = viewChild<ElementRef<HTMLImageElement>>('my-view-child'); // ^? Signal<ElementRef<HTMLImageElement>> myViewChildren = viewChildren<ElementRef<HTMLImageElement>>('my-view-children'); // ^? Signal<ReadonlyArray<ElementRef<HTMLImageElement>>>
// Setter queries are not supported @ViewChild('my-input') set myInput(el: ElementRef<HTMLInputElement>) { el.nativeElement.focus(); }}In order to run the schematics for all the project in the app you have to run the following script:
ng g ngxtension-plugin:convert-queriesIf you want to specify the project name you can pass the --project param.
ng g ngxtension-plugin:convert-queries --project=<project-name>If you want to run the schematic for a specific component or directive you can pass the --path param.
ng g ngxtension-plugin:convert-queries --path=<path-to-ts-file>Usage with Nx
Section titled “Usage with Nx”To use the schematics on a Nx monorepo you just swap ng with nx
Example:
nx g ngxtension-plugin:convert-queries --project=<project-name>