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
This commit is contained in:
Jessica Janiuk 2023-12-05 13:05:25 -05:00 committed by Dylan Hunn
parent 5a0ed28c9d
commit 01b18a4248
2 changed files with 52 additions and 0 deletions

View file

@ -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, `<ng-template [ngTemplateOutlet]="${name}"></ng-template>`);
}
return migrated;
}
/**
* determines if the CommonModule can be safely removed from imports
*/

View file

@ -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', [
`<button *ngIf="active; else defaultTemplate">`,
` Hello!`,
`</button>`,
].join('\n'));
await runMigration();
const content = tree.readContent('/comp.html');
expect(content).toBe([
`@if (active) {`,
` <button>`,
` Hello!`,
` </button>`,
`} @else {`,
` <ng-template [ngTemplateOutlet]="defaultTemplate"></ng-template>`,
`}`,
].join('\n'));
});
});
describe('formatting', () => {