Skip to content

Commit 9ea5868

Browse files
committed
fix(@angular/cli): update zoneless migration tool to handle ChangeDetectionStrategy.Eager
`ChangeDetectionStrategy.Default` is deprecated. This update ensures the zoneless migration tool correctly identifies, handles, and prompts for the new `ChangeDetectionStrategy.Eager` strategy in component metadata.
1 parent 53ada26 commit 9ea5868

File tree

4 files changed

+12
-17
lines changed

4 files changed

+12
-17
lines changed

packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate-single-file.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { sendDebugMessage } from './send-debug-message';
1616
import { getImportSpecifier, loadTypescript } from './ts-utils';
1717
import type { MigrationResponse } from './types';
1818

19+
const supportedStrategies: ReadonlySet<string> = new Set(['OnPush', 'Default', 'Eager']);
20+
1921
export async function migrateSingleFile(
2022
sourceFile: SourceFile,
2123
extras: RequestHandlerExtra<ServerRequest, ServerNotification>,
@@ -31,7 +33,7 @@ export async function migrateSingleFile(
3133
return unsupportedZoneUseResponse;
3234
}
3335

34-
let detectedStrategy: 'OnPush' | 'Default' | undefined;
36+
let detectedStrategy: string | undefined;
3537
let hasComponentDecorator = false;
3638

3739
const componentSpecifier = await getImportSpecifier(sourceFile, '@angular/core', 'Component');
@@ -63,7 +65,7 @@ export async function migrateSingleFile(
6365
prop.initializer.expression.getText(sourceFile) === 'ChangeDetectionStrategy'
6466
) {
6567
const strategy = prop.initializer.name.text;
66-
if (strategy === 'OnPush' || strategy === 'Default') {
68+
if (supportedStrategies.has(strategy)) {
6769
detectedStrategy = strategy;
6870

6971
return;
@@ -77,13 +79,7 @@ export async function migrateSingleFile(
7779
ts.forEachChild(node, visit);
7880
});
7981

80-
if (
81-
!hasComponentDecorator ||
82-
// component uses OnPush. We don't have anything more to do here.
83-
detectedStrategy === 'OnPush' ||
84-
// Explicit default strategy, assume there's a reason for it (already migrated, or is a library that hosts Default components) and skip.
85-
detectedStrategy === 'Default'
86-
) {
82+
if (!hasComponentDecorator || (detectedStrategy && supportedStrategies.has(detectedStrategy))) {
8783
sendDebugMessage(
8884
`Component decorator found with strategy: ${detectedStrategy} in file: ${sourceFile.fileName}. Skipping migration for file.`,
8985
extras,

packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/migrate-single-file_spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,15 @@ describe('migrateSingleFile', () => {
8585
expect(result).toBeNull();
8686
});
8787

88-
it('should return null if component has ChangeDetectionStrategy.Default', async () => {
88+
it('should return null if component has ChangeDetectionStrategy.Eager', async () => {
8989
const fileName = 'app.component.ts';
9090
const content = `
9191
import { Component, ChangeDetectionStrategy } from '@angular/core';
9292
9393
@Component({
9494
selector: 'app-root',
9595
template: 'Hello',
96-
changeDetection: ChangeDetectionStrategy.Default,
96+
changeDetection: ChangeDetectionStrategy.Eager,
9797
})
9898
export class AppComponent {}
9999
`;

packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/prompts.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,11 @@ export function generateZonelessMigrationInstructionsForComponent(
130130
* **(Preferred) Convert to Signal**: The best approach is to convert the property to an Angular Signal. This is the most idiomatic and future-proof way to handle state in zoneless applications.
131131
* **(Alternative) Use \`markForCheck()\`**: If converting to a signal is too complex or would require extensive refactoring, you can instead inject \`ChangeDetectorRef\` and call \`this.cdr.markForCheck()\` immediately after the property is updated.
132132
133-
#### Step 2: Add \`ChangeDetectionStrategy.Default\`
133+
#### Step 2: Add \`ChangeDetectionStrategy.Eager\`
134134
After you have refactored all necessary properties, you must update the component's decorator to explicitly set the change detection strategy.
135135
136136
1. Add \`ChangeDetectionStrategy\` to the import from \`@angular/core\`.
137-
2. In the \`@Component\` decorator, add the property \`changeDetection: ChangeDetectionStrategy.Default\`.
137+
2. In the \`@Component\` decorator, add the property \`changeDetection: ChangeDetectionStrategy.Eager\`.
138138
3. Add a \`// TODO\` comment above this line explaining that the component should be fully migrated to \`OnPush\` after the application has been tested with these changes.
139139
140140
Example:
@@ -143,14 +143,14 @@ export function generateZonelessMigrationInstructionsForComponent(
143143
...
144144
// TODO: This component has been partially migrated to be zoneless-compatible.
145145
// After testing, this should be updated to ChangeDetectionStrategy.OnPush.
146-
changeDetection: ChangeDetectionStrategy.Default,
146+
changeDetection: ChangeDetectionStrategy.Eager,
147147
})
148148
\`\`\`
149149
150150
### IMPORTANT: Rules and Constraints
151151
You must follow these rules without exception:
152152
1. **DO** apply one of the two refactoring strategies (signals or \`markForCheck()\`) for all relevant component properties.
153-
2. **DO** add \`changeDetection: ChangeDetectionStrategy.Default\` with the specified TODO comment as the final code change.
153+
2. **DO** add \`changeDetection: ChangeDetectionStrategy.Eager\` with the specified TODO comment as the final code change.
154154
3. **DO NOT** use \`ChangeDetectionStrategy.OnPush\`. This will be the next step in the migration, but it is not part of this task.
155155
4. **DO NOT** modify properties that are already signals or are used with the \`async\` pipe in the template, as they are already zoneless-compatible.
156156
5. **DO NOT** make any changes to files other than the component file at \`${filePath}\` and its direct template/style files if necessary.

packages/angular/cli/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,7 @@ async function categorizeFile(
204204
componentTestFiles.add(sourceFile);
205205
} else if (componentSpecifier) {
206206
if (
207-
!content.includes('changeDetectionStrategy: ChangeDetectionStrategy.OnPush') &&
208-
!content.includes('changeDetectionStrategy: ChangeDetectionStrategy.Default')
207+
!/changeDetectionStrategy:\s*ChangeDetectionStrategy\.(?:OnPush|Default|Eager)/.test(content)
209208
) {
210209
filesWithComponents.add(sourceFile);
211210
} else {

0 commit comments

Comments
 (0)