---
name: standalone-component-migrator
description: This skill should be used when converting Angular NgModule-based components to standalone architecture. It handles dependency analysis, template scanning, route refactoring, and test updates. Use this skill when the user requests component migration to standalone, mentions "convert to standalone", or wants to modernize Angular components to the latest patterns.
---

# Standalone Component Migrator

## Overview

Automate the conversion of Angular components from NgModule-based architecture to standalone components with explicit imports. This skill analyzes component dependencies, updates routing configurations, migrates tests, and optionally converts to modern Angular control flow syntax (@if, @for, @switch).

## When to Use This Skill

Invoke this skill when:
- User requests component conversion to standalone
- User mentions "migrate to standalone" or "modernize component"
- User wants to remove NgModule declarations
- User references Angular's standalone component architecture

## Migration Workflow

### Step 1: Analyze Component Dependencies

1. **Read Component File**
   - Identify component decorator configuration
   - Note selector, template path, style paths
   - Check if already standalone

2. **Analyze Template**
   - Read template file (HTML)
   - Scan for directives: `*ngIf`, `*ngFor`, `*ngSwitch` → requires CommonModule
   - Scan for forms: `ngModel`, `formControl` → requires FormsModule or ReactiveFormsModule
   - Scan for built-in pipes: `async`, `date`, `json` → CommonModule
   - Scan for custom components: identify all component selectors
   - Scan for router directives: `routerLink`, `router-outlet` → RouterModule

3. **Find Parent NgModule**
   - Search for NgModule that declares this component
   - Read NgModule file to understand current imports

### Step 2: Convert Component to Standalone

Add `standalone: true` and explicit imports array:

```typescript
// BEFORE
import { Component } from '@angular/core';

@Component({
  selector: 'app-my-component',
  templateUrl: './my-component.component.html'
})
export class MyComponent { }

// AFTER
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { ChildComponent } from './child.component';
import { CustomPipe } from '@isa/utils/pipes';

@Component({
  selector: 'app-my-component',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    RouterModule,
    ChildComponent,
    CustomPipe
  ],
  templateUrl: './my-component.component.html'
})
export class MyComponent { }
```

### Step 3: Update Parent NgModule

Remove component from declarations, add to imports if exported:

```typescript
// BEFORE
@NgModule({
  declarations: [MyComponent, OtherComponent],
  imports: [CommonModule],
  exports: [MyComponent]
})

// AFTER
@NgModule({
  declarations: [OtherComponent],
  imports: [CommonModule, MyComponent], // Import standalone component
  exports: [MyComponent]
})
```

If NgModule becomes empty (no declarations), consider removing it entirely.

### Step 4: Update Routes (if applicable)

Convert to lazy-loaded standalone component:

```typescript
// BEFORE
const routes: Routes = [
  { path: 'feature', component: MyComponent }
];

// AFTER (lazy loading)
const routes: Routes = [
  {
    path: 'feature',
    loadComponent: () => import('./my-component.component').then(m => m.MyComponent)
  }
];
```

### Step 5: Update Tests

Convert test configuration:

```typescript
// BEFORE
TestBed.configureTestingModule({
  declarations: [MyComponent],
  imports: [CommonModule, FormsModule]
});

// AFTER
TestBed.configureTestingModule({
  imports: [MyComponent] // Component imports its own dependencies
});
```

### Step 6: Optional - Migrate to Modern Control Flow

If requested, convert to new Angular control flow syntax:

```typescript
// OLD
<div *ngIf="condition">Content</div>
<div *ngFor="let item of items; trackBy: trackById">{{ item.name }}</div>
<div [ngSwitch]="value">
  <div *ngSwitchCase="'a'">A</div>
  <div *ngSwitchDefault>Default</div>
</div>

// NEW
@if (condition) {
  <div>Content</div>
}
@for (item of items; track item.id) {
  <div>{{ item.name }}</div>
}
@switch (value) {
  @case ('a') { <div>A</div> }
  @default { <div>Default</div> }
}
```

### Step 7: Validate and Test

1. **Compile Check**
   ```bash
   npx tsc --noEmit
   ```

2. **Run Tests**
   ```bash
   npx nx test [library-name] --skip-nx-cache
   ```

3. **Lint Check**
   ```bash
   npx nx lint [library-name]
   ```

4. **Verify Application Runs**
   ```bash
   npm start
   ```

## Common Import Patterns

| Template Usage | Required Import |
|---------------|-----------------|
| `*ngIf`, `*ngFor`, `*ngSwitch` | `CommonModule` |
| `ngModel` | `FormsModule` |
| `formControl`, `formGroup` | `ReactiveFormsModule` |
| `routerLink`, `router-outlet` | `RouterModule` |
| `async`, `date`, `json` pipes | `CommonModule` |
| Custom components | Direct component import |
| Custom pipes | Direct pipe import |

## Error Handling

**Issue: Circular dependencies**
- Extract shared interfaces to util library
- Use dependency injection for services
- Avoid component A importing component B when B imports A

**Issue: Missing imports causing template errors**
- Check browser console for specific errors
- Verify all template dependencies are in imports array
- Use Angular Language Service in IDE for hints

## References

- Angular Standalone Components: https://angular.dev/guide/components/importing
- Modern Control Flow: https://angular.dev/guide/templates/control-flow
- CLAUDE.md Component Architecture section
