Skip to content

Commit 01b18a4

Browse files
thePunderWomandylhunn
authored andcommitted
fix(migrations): handle templates outside of component in cf migration (#53368)
If a template is passed in as an input, the ng-template will not exist in the same component template. This will leave a template placeholder behind. This fix ensures that template placeholder gets turned into a template outlet. fixes: #53361 PR Close #53368
1 parent 5a0ed28 commit 01b18a4

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

packages/core/schematics/ng-generate/control-flow-migration/util.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,12 +355,30 @@ export function processNgTemplates(template: string): {migrated: string, err: Er
355355
updateTemplates(template, templates);
356356
}
357357
}
358+
// template placeholders may still exist if the ng-template name is not
359+
// present in the component. This could be because it's passed in from
360+
// another component. In that case, we need to replace any remaining
361+
// template placeholders with template outlets.
362+
template = replaceRemainingPlaceholders(template);
358363
return {migrated: template, err: undefined};
359364
} catch (err) {
360365
return {migrated: template, err: err as Error};
361366
}
362367
}
363368

369+
function replaceRemainingPlaceholders(template: string): string {
370+
const replaceRegex = new RegExp(`#\\w*\\|`, 'g');
371+
const placeholders = [...template.matchAll(replaceRegex)];
372+
let migrated = template;
373+
for (let ph of placeholders) {
374+
const placeholder = ph[0];
375+
const name = placeholder.slice(1, placeholder.length - 1);
376+
migrated =
377+
template.replace(placeholder, `<ng-template [ngTemplateOutlet]="${name}"></ng-template>`);
378+
}
379+
return migrated;
380+
}
381+
364382
/**
365383
* determines if the CommonModule can be safely removed from imports
366384
*/

packages/core/schematics/test/control_flow_migration_spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4012,6 +4012,40 @@ describe('control flow migration', () => {
40124012
`}\n`,
40134013
].join('\n'));
40144014
});
4015+
4016+
it('should add an ngTemplateOutlet when the template placeholder does not match a template',
4017+
async () => {
4018+
writeFile('/comp.ts', `
4019+
import {Component} from '@angular/core';
4020+
import {NgIf} from '@angular/common';
4021+
4022+
@Component({
4023+
templateUrl: './comp.html'
4024+
})
4025+
class Comp {
4026+
show = false;
4027+
}
4028+
`);
4029+
4030+
writeFile('/comp.html', [
4031+
`<button *ngIf="active; else defaultTemplate">`,
4032+
` Hello!`,
4033+
`</button>`,
4034+
].join('\n'));
4035+
4036+
await runMigration();
4037+
const content = tree.readContent('/comp.html');
4038+
4039+
expect(content).toBe([
4040+
`@if (active) {`,
4041+
` <button>`,
4042+
` Hello!`,
4043+
` </button>`,
4044+
`} @else {`,
4045+
` <ng-template [ngTemplateOutlet]="defaultTemplate"></ng-template>`,
4046+
`}`,
4047+
].join('\n'));
4048+
});
40154049
});
40164050

40174051
describe('formatting', () => {

0 commit comments

Comments
 (0)