diff --git a/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.test.ts b/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.test.ts
index 68c19d8..67b1ad7 100644
--- a/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.test.ts
+++ b/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.test.ts
@@ -167,6 +167,53 @@ describe("migrateComponents", () => {
);
});
+ it("should detect and import icons in conditional used in the template", async () => {
+ const project = new Project({ useInMemoryFileSystem: true });
+
+ const component = `
+ import { Component } from "@angular/core";
+
+ @Component({
+ selector: 'my-component',
+ template: \`\`,
+ standalone: true
+ })
+ export class MyComponent {
+ isLogo = true;
+ }
+ `;
+
+ const componentSourceFile = project.createSourceFile(
+ "foo.component.ts",
+ dedent(component),
+ );
+
+ await migrateComponents(project, { dryRun: false });
+
+ expect(dedent(componentSourceFile.getText())).toBe(
+ dedent(`
+ import { Component } from "@angular/core";
+ import { addIcons } from "ionicons";
+ import { logoIonic, alert } from "ionicons/icons";
+ import { IonIcon } from "@ionic/angular/standalone";
+
+ @Component({
+ selector: 'my-component',
+ template: \`\`,
+ standalone: true,
+ imports: [IonIcon]
+ })
+ export class MyComponent {
+ isLogo = true;
+
+ constructor() {
+ addIcons({ logoIonic, alert });
+ }
+ }
+ `),
+ );
+ });
+
it("should remove duplicate imports from existing declarations", async () => {
const project = new Project({ useInMemoryFileSystem: true });
diff --git a/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.ts b/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.ts
index d370ea1..ece332e 100644
--- a/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.ts
+++ b/packages/cli/src/angular/migrations/standalone/0002-import-standalone-component.ts
@@ -292,10 +292,38 @@ function detectIonicComponentsAndIcons(htmlAsString: string, filePath: string) {
*/
const iconNameMatch = skippedIcon.match(iconNameRegex);
+ const deepGetIconConditional = (
+ ast: typeof boundNameAttribute.value.ast,
+ icons: string[],
+ ): string[] => {
+ if (ast.trueExp.type === "LiteralPrimitive") {
+ if (!ionIcons.includes(ast.trueExp.value)) {
+ ionIcons.push(ast.trueExp.value);
+ }
+ } else if (ast.trueExp.type === "Conditional") {
+ deepGetIconConditional(ast.trueExp, icons);
+ } else {
+ skippedIconsHtml.push(skippedIcon);
+ }
+
+ if (ast.falseExp.type === "LiteralPrimitive") {
+ if (!ionIcons.includes(ast.falseExp.value)) {
+ ionIcons.push(ast.falseExp.value);
+ }
+ } else if (ast.falseExp.type === "Conditional") {
+ deepGetIconConditional(ast.falseExp, icons);
+ } else {
+ skippedIconsHtml.push(skippedIcon);
+ }
+ return icons;
+ };
+
if (iconNameMatch) {
if (!ionIcons.includes(iconNameMatch[1])) {
ionIcons.push(iconNameMatch[1]);
}
+ } else if (boundNameAttribute.value.ast.type === "Conditional") {
+ deepGetIconConditional(boundNameAttribute.value.ast, ionIcons);
} else {
// IonIcon name is a calculated value from a variable or function.
// We can't determine the value of the name at this time.