Skip to main content

migrate

Migrate a component or directive to Angular 22+ signal-based patterns

ソース情報

リポジトリ
SAP/fundamental-ngx
ソースの最終更新活動
2026年7月16日 15:51
検出された SKILL.md の言語
英語
スター
295
フォーク
149

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
migrate
description
Migrate a component or directive to Angular 22+ signal-based patterns
argument-hint
["component-path-or-folder"]
# Angular 22+ Migration: $ARGUMENTS If `$ARGUMENTS` is empty, ask the user for a component path or folder before proceeding. ## Phase 1: Analyze Read all files in the target path. For each component, directive, or service, scan for migration items below. If a folder is given, process all `.ts` and `.html` files within it. ### What to migrate **Inputs / Outputs / Models:** - `@Input()` → `input()` or `input.required()` - `@Input()` with setter → `input()` + `linkedSignal()` (preferred) or `effect()` (only for DOM side effects) - `@Input()` + `@Output()` pair (e.g. `value` / `valueChange`) → `model()` - `@Output()` → `output()` - Boolean inputs: add `{ transform: booleanAttribute }` - Number inputs: add `{ transform: numberAttribute }` **Host bindings:** - `@HostBinding('class.x')` → `host: { '[class.x]': 'expr()' }` - `@HostBinding('attr.x')` → `host: { '[attr.x]': 'expr()' }` - `@HostBinding('style.x')` → `host: { '[style.x]': 'expr()' }` - `@HostListener('event')` → `host: { '(event)': 'handler($event)' }` **Queries:** - `@ViewChild()` → `viewChild()` or `viewChild.required()` - `@ViewChildren()` → `viewChildren()` - `@ContentChild()` → `contentChild()` - `@ContentChildren()` → `contentChildren()` **Template syntax:** - `*ngIf` → `@if` - `*ngFor` → `@for` (requires `track` expression) - `*ngSwitch` / `*ngSwitchCase` → `@switch` / `@case` **State management:** - `BehaviorSubject` used for local component state → `signal()` - `BehaviorSubject` + `combineLatest` → `computed()` - `Subject<void>` used only to trigger side effects → `effect()` - `effect()` that only calls `signal.set()` for derived state → `computed()` or `linkedSignal` - Redundant `markForCheck()` after signal updates → remove - Object/array mutation in place + `signal.set()` with same ref → immutable update with `signal.update()` **CSS class building:** - `CssClassBuilder` + `@applyCssClass` → `computed()` returning class string + `host: { '[class]': '_cssClass()' }` **Cleanup patterns:** - Custom `DestroyedService` → `DestroyRef` + `takeUntilDestroyed()` - `ngOnDestroy` only for `destroy$.next()` → remove entirely after migration **Decorator cleanup:** - Remove `standalone: true` (default since Angular 19) - Remove `allowSignalWrites` option in `effect()` (the option no longer exists) **Imports:** - Deprecated `*Module` classes → individual component/directive imports **Member ordering** (ESLint enforced): 1. Decorated properties (any remaining `@Input`, `@Output`, `@ViewChild`) 2. Signal inputs/outputs (`input()`, `output()`, `model()`) 3. Public → Protected → Private fields 4. Constructor 5. Public → Protected → Private methods ### What NOT to migrate Do NOT convert these — they should stay as-is: - **RxJS for async operations**: HTTP calls, WebSocket streams, timers, interval-based logic → keep as Observable - **BehaviorSubject with complex operators**: `switchMap`, `debounceTime`, `distinctUntilChanged`, `combineLatest` with async sources → keep as RxJS - **Plain properties with no reactive consumer**: If nothing in template, host binding, computed, or effect reads it → keep as plain property, do not wrap in `signal()` - **Signals for internal bookkeeping**: One-time flags, cached DOM measurements, counters with no reactive consumer → use plain property ### Migration is optional for existing code The migration targets are recommendations, not mandatory fixes. Present all findings but let the user decide scope. Existing `@Input()` / `@Output()` decorators are valid — only migrate them if the user wants to or if the code is being substantially reworked. ## Phase 2: Present Plan Output a structured migration plan: ``` ## Migration Plan: [component name] ### Files affected - path/to/component.ts - path/to/component.html - path/to/component.spec.ts ### Inputs / Outputs | Current | Migration | Notes | |---------|-----------|-------| | `@Input() label: string` | `readonly label = input<string>('')` | | | `@Input() disabled: boolean` | `readonly disabled = input(false, { transform: booleanAttribute })` | | | `@Input() value` + `@Output() valueChange` | `readonly value = model<T>()` | Two-way binding | ### Host Bindings | Current | Migration | |---------|-----------| | `@HostBinding('class.is-open')` | `host: { '[class.is-open]': 'isOpen()' }` | ### Template Changes | Current | Migration | |---------|-----------| | `*ngIf="condition"` | `@if (condition) { ... }` | | `*ngFor="let item of items"` | `@for (item of items; track item.id) { ... }` | ### State Management | Current | Migration | Reason | |---------|-----------|--------| | `BehaviorSubject<boolean>` | `signal(false)` | Local state, no async consumers | ### Skipped (intentionally not migrated) | Item | Reason | |------|--------| | `httpData$` Observable | Async HTTP stream | ### Test Updates - [ ] Replace `component.input = value` with `fixture.componentRef.setInput('input', value)` - [ ] Update module imports to individual components - [ ] Verify existing tests still pass after migration ### Docs Updates - [ ] Update examples if public API changed (input names, usage patterns) - [ ] Ensure examples use individual imports, not deprecated modules ### Breaking Changes - [ ] List any renamed/removed inputs or outputs - [ ] Draft BREAKING CHANGE footer if needed ``` **Stop here and wait for approval before proceeding.** ## Phase 3: Execute After approval: 1. Apply all migrations from the approved plan 2. Format code: `yarn format` 3. Run build: `nx run <library>:build` 4. Run lint: `nx run <library>:lint` 5. Run tests: `nx run <library>:test --testfile=<spec-file> --skip-nx-cache` 6. Report results and any issues
GitHubで見る