diff --git a/integration/mdc-migration/golden/src/app/components/chips/chips.component.html b/integration/mdc-migration/golden/src/app/components/chips/chips.component.html index fc32a278e89b..f097b1ae3485 100644 --- a/integration/mdc-migration/golden/src/app/components/chips/chips.component.html +++ b/integration/mdc-migration/golden/src/app/components/chips/chips.component.html @@ -15,12 +15,12 @@

Chips example

Favorite Fruits - + {{fruit.name}} - + { it('should update standalone chips', async () => { await runMigrationTest('', ''); }); + + it('should update mat-chip with an *ngFor', async () => { + await runMigrationTest( + ` + + {{chip}} + + `, + ` + + {{chip}} + + `, + ); + }); + + it('should update a chip listbox with a nested ng-container', async () => { + await runMigrationTest( + ` + + + + {{chip}} + + + + `, + ` + + + + {{chip}} + + + + `, + ); + }); + + it('should update a chip with an *ngIf', async () => { + await runMigrationTest( + '', + '', + ); + }); + + it('should update a chip grid with an *ngFor', async () => { + await runMigrationTest( + ` + + {{chip}} + + + `, + ` + + {{chip}} + + + `, + ); + }); }); diff --git a/src/material/schematics/ng-generate/mdc-migration/rules/tree-traversal.spec.ts b/src/material/schematics/ng-generate/mdc-migration/rules/tree-traversal.spec.ts index ff90a640bd17..56e610a10b30 100644 --- a/src/material/schematics/ng-generate/mdc-migration/rules/tree-traversal.spec.ts +++ b/src/material/schematics/ng-generate/mdc-migration/rules/tree-traversal.spec.ts @@ -48,6 +48,49 @@ function runClearAttributeTest(html: string, result: string): void { } describe('#visitElements', () => { + describe('visitElements', () => { + it('should traverse elements with an *ngFor', () => { + const visitedElements: string[] = []; + const template = ` + + + + + + `; + + visitElements(parseTemplate(template).nodes, node => visitedElements.push(node.name)); + expect(visitedElements).toEqual(['parent', 'child', 'grandchild']); + }); + + it('should traverse elements inside ng-container', () => { + const visitedElements: string[] = []; + const template = ` + + + + + + + + + + + + `; + + visitElements(parseTemplate(template).nodes, node => visitedElements.push(node.name)); + expect(visitedElements).toEqual([ + 'ng-container', + 'parent', + 'ng-container', + 'child', + 'ng-container', + 'grandchild', + ]); + }); + }); + describe('tag name replacements', () => { it('should handle basic cases', async () => { runTagNameDuplicationTest('', ''); diff --git a/src/material/schematics/ng-generate/mdc-migration/rules/tree-traversal.ts b/src/material/schematics/ng-generate/mdc-migration/rules/tree-traversal.ts index f6d4188c1f45..6ac6dc2e88e6 100644 --- a/src/material/schematics/ng-generate/mdc-migration/rules/tree-traversal.ts +++ b/src/material/schematics/ng-generate/mdc-migration/rules/tree-traversal.ts @@ -10,6 +10,7 @@ import { ParsedTemplate, TmplAstElement, TmplAstNode, + TmplAstTemplate, parseTemplate as parseTemplateUsingCompiler, } from '@angular/compiler'; @@ -32,9 +33,18 @@ export function visitElements( nodes.reverse(); for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; - if (node instanceof TmplAstElement) { + const isElement = node instanceof TmplAstElement; + + if (isElement) { preorderCallback(node); + } + + // Descend both into elements and templates in order to cover cases like `*ngIf` and `*ngFor`. + if (isElement || node instanceof TmplAstTemplate) { visitElements(node.children, preorderCallback, postorderCallback); + } + + if (isElement) { postorderCallback(node); } } @@ -46,8 +56,8 @@ export function visitElements( * * For more details, see https://github.com/angular/angular/blob/4332897baa2226ef246ee054fdd5254e3c129109/packages/compiler-cli/src/ngtsc/annotations/component/src/resources.ts#L230. * - * @param html text of the template to parse - * @param filePath URL to use for source mapping of the parsed template + * @param template text of the template to parse + * @param templateUrl URL to use for source mapping of the parsed template * @returns the updated template html. */ export function parseTemplate(template: string, templateUrl: string = ''): ParsedTemplate {