Skip to content

Commit 58a96e0

Browse files
thePunderWomandylhunn
authored andcommitted
fix(migrations): CF Migration add support for ngIf with just a then (#53297)
Prior to this fix, the expectation that anytime then was used, else would always be present. That is not a valid assumption. fixes: #53287 PR Close #53297
1 parent 45064f1 commit 58a96e0

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

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

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,12 @@ function migrateNgIf(etm: ElementToMigrate, tmpl: string, offset: number): Resul
7474
if (etm.thenAttr !== undefined || etm.elseAttr !== undefined) {
7575
// bound if then / if then else
7676
return buildBoundIfElseBlock(etm, tmpl, offset);
77-
} else if (matchThen && matchThen.length > 0) {
77+
} else if (matchThen && matchThen.length > 0 && matchElse && matchElse.length > 0) {
78+
// then else
7879
return buildStandardIfThenElseBlock(etm, tmpl, matchThen[0], matchElse![0], offset);
80+
} else if (matchThen && matchThen.length > 0) {
81+
// just then
82+
return buildStandardIfThenBlock(etm, tmpl, matchThen[0], offset);
7983
} else if ((matchElse && matchElse.length > 0)) {
8084
// just else
8185
return buildStandardIfElseBlock(etm, tmpl, matchElse![0], offset);
@@ -189,6 +193,17 @@ function buildStandardIfThenElseBlock(
189193
return buildIfThenElseBlock(etm, tmpl, condition, thenPlaceholder, elsePlaceholder, offset);
190194
}
191195

196+
function buildStandardIfThenBlock(
197+
etm: ElementToMigrate, tmpl: string, thenString: string, offset: number): Result {
198+
// includes the mandatory semicolon before as
199+
const condition = etm.getCondition()
200+
.replace(' as ', '; as ')
201+
// replace 'let' with 'as' whatever spaces are between ; and 'let'
202+
.replace(/;\s*let/g, '; as');
203+
const thenPlaceholder = `#${etm.getTemplateName(thenString)}|`;
204+
return buildIfThenBlock(etm, tmpl, condition, thenPlaceholder, offset);
205+
}
206+
192207
function buildIfThenElseBlock(
193208
etm: ElementToMigrate, tmpl: string, condition: string, thenPlaceholder: string,
194209
elsePlaceholder: string, offset: number): Result {
@@ -214,3 +229,28 @@ function buildIfThenElseBlock(
214229

215230
return {tmpl: updatedTmpl, offsets: {pre, post}};
216231
}
232+
233+
function buildIfThenBlock(
234+
etm: ElementToMigrate, tmpl: string, condition: string, thenPlaceholder: string,
235+
offset: number): Result {
236+
const lbString = etm.hasLineBreaks ? '\n' : '';
237+
238+
const originals = getOriginals(etm, tmpl, offset);
239+
240+
const startBlock = `@if (${condition}) {${lbString}`;
241+
242+
const postBlock = thenPlaceholder + `${lbString}}`;
243+
const ifThenBlock = startBlock + postBlock;
244+
245+
const tmplStart = tmpl.slice(0, etm.start(offset));
246+
const tmplEnd = tmpl.slice(etm.end(offset));
247+
248+
const updatedTmpl = tmplStart + ifThenBlock + tmplEnd;
249+
250+
// We ignore the contents of the element on if then else.
251+
// If there's anything there, we need to account for the length in the offset.
252+
const pre = originals.start.length + originals.childLength - startBlock.length;
253+
const post = originals.end.length - postBlock.length;
254+
255+
return {tmpl: updatedTmpl, offsets: {pre, post}};
256+
}

packages/core/schematics/test/control_flow_migration_spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,38 @@ describe('control flow migration', () => {
487487
].join('\n'));
488488
});
489489

490+
it('should migrate an if case on an empty container', async () => {
491+
writeFile('/comp.ts', `
492+
import {Component} from '@angular/core';
493+
import {NgIf} from '@angular/common';
494+
495+
@Component({
496+
templateUrl: './comp.html'
497+
})
498+
class Comp {
499+
show = false;
500+
}
501+
`);
502+
503+
writeFile('/comp.html', [
504+
`<ng-container`,
505+
` *ngIf="true; then template"`,
506+
`></ng-container>`,
507+
`<ng-template #template>`,
508+
` Hello!`,
509+
`</ng-template> `,
510+
].join('\n'));
511+
512+
await runMigration();
513+
const content = tree.readContent('/comp.html');
514+
515+
expect(content).toBe([
516+
`@if (true) {`,
517+
` Hello!`,
518+
`}\n`,
519+
].join('\n'));
520+
});
521+
490522
it('should migrate an if case with an ng-template with i18n', async () => {
491523
writeFile('/comp.ts', `
492524
import {Component} from '@angular/core';

0 commit comments

Comments
 (0)