diff --git a/packages/core/schematics/ng-generate/control-flow-migration/util.ts b/packages/core/schematics/ng-generate/control-flow-migration/util.ts index e0264d4c022..87e8ecfec9a 100644 --- a/packages/core/schematics/ng-generate/control-flow-migration/util.ts +++ b/packages/core/schematics/ng-generate/control-flow-migration/util.ts @@ -355,12 +355,30 @@ export function processNgTemplates(template: string): {migrated: string, err: Er updateTemplates(template, templates); } } + // template placeholders may still exist if the ng-template name is not + // present in the component. This could be because it's passed in from + // another component. In that case, we need to replace any remaining + // template placeholders with template outlets. + template = replaceRemainingPlaceholders(template); return {migrated: template, err: undefined}; } catch (err) { return {migrated: template, err: err as Error}; } } +function replaceRemainingPlaceholders(template: string): string { + const replaceRegex = new RegExp(`#\\w*\\|`, 'g'); + const placeholders = [...template.matchAll(replaceRegex)]; + let migrated = template; + for (let ph of placeholders) { + const placeholder = ph[0]; + const name = placeholder.slice(1, placeholder.length - 1); + migrated = + template.replace(placeholder, ``); + } + return migrated; +} + /** * determines if the CommonModule can be safely removed from imports */ diff --git a/packages/core/schematics/test/control_flow_migration_spec.ts b/packages/core/schematics/test/control_flow_migration_spec.ts index 9af197dd0e1..aac93e7096f 100644 --- a/packages/core/schematics/test/control_flow_migration_spec.ts +++ b/packages/core/schematics/test/control_flow_migration_spec.ts @@ -4012,6 +4012,40 @@ describe('control flow migration', () => { `}\n`, ].join('\n')); }); + + it('should add an ngTemplateOutlet when the template placeholder does not match a template', + async () => { + writeFile('/comp.ts', ` + import {Component} from '@angular/core'; + import {NgIf} from '@angular/common'; + + @Component({ + templateUrl: './comp.html' + }) + class Comp { + show = false; + } + `); + + writeFile('/comp.html', [ + ``, + ].join('\n')); + + await runMigration(); + const content = tree.readContent('/comp.html'); + + expect(content).toBe([ + `@if (active) {`, + ` `, + `} @else {`, + ` `, + `}`, + ].join('\n')); + }); }); describe('formatting', () => {