Angular Component Standalone Default Change in v19
Problem Statement
After updating Angular to version 19, many developers encounter two related errors:
Component AppComponent is standalone, and cannot be declared in an NgModuleor
'imports' is only valid on a component that is standalone.These errors occur because Angular 19 changed the default component behavior. Previously in v18, components were not standalone by default (standalone: false). Now in v19, all components are standalone by default (standalone: true). This means:
- Any component declared in an
NgModulemust now explicitly setstandalone: false - Non-standalone components cannot use the
importsarray (only valid for standalone components)
Solution
Best Practice: Use Angular Update Migration
Run the official Angular migration command to automatically fix compatibility issues:
ng updateThis will:
- Add
standalone: falseto non-standalone components - Remove incompatible
importsarrays from non-standalone components - Handle other v19 migration tasks
Manual Fixes
1. Add standalone: false to components
For any component declared in an NgModule, add standalone: false:
@Component({
standalone: false, // Required for non-standalone components
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {}2. Remove imports from non-standalone components
Non-standalone components (those with standalone: false) cannot have an imports array. Remove them entirely:
@Component({
standalone: false,
imports: [CommonModule], // REMOVE THIS LINE
// ...
})
export class NonStandaloneComponent {}Migration Script for Large Projects (Use with Caution)
For projects with many components, this Unix script adds standalone: false to components without existing imports:
# Components
find ./src -name "*.component.ts" -exec grep -L "imports:" {} \; | xargs grep -l "@Component" | grep -L "standalone:" | xargs sed -i '' -E 's/@Component\(\{/@Component({\n standalone: false,/g'
# Directives
find ./src -name "*.directive.ts" -exec grep -L "imports:" {} \; | xargs grep -l "@Directive" | grep -L "standalone:" | xargs sed -i '' -E 's/@Directive\(\{/@Directive({\n standalone: false,/g'
# Pipes
find ./src -name "*.pipe.ts" -exec grep -L "imports:" {} \; | xargs grep -l "@Pipe" | grep -L "standalone:" | xargs sed -i '' -E 's/@Pipe\(\{/@Pipe({\n standalone: false,/g'WARNING
Backup your code before running scripts!
macOS: Use sed -i '' ...
Linux: Use sed -i ... without ''
Key Architecture Changes
These changes occur because Angular is shifting toward a standalone-first architecture:
- Standalone components manage their own dependencies
NgModuledeclarations require explicit non-standalone status- Angular recommends using standalone components for new projects
For mixed architectures:
- Standalone components: Use
importsarray - Non-standalone components: Must be declared in an
NgModule - Combine both approaches with
imports: [ModuleContainingComponents]in standalone components