Standalone by Default (v20+)
📚 What Changed in v20?
Starting with Angular 19/20, standalone: true is the default:
- No need to declare: standalone: true is implicit
- To opt-out: Must explicitly set standalone: false
- Cleaner decorators: Less boilerplate in @Component
- NgModules still work: For legacy code compatibility
📅 Standalone Evolution
v14
Introduced as opt-in
Required explicit standalone: true
v17
Default for ng generate
CLI generates standalone by default
v19+
Language default
standalone: true is implicit, no declaration needed
🎯 Interview Questions
- Q1: Do you need to write standalone: true in Angular 20?
- A: No! It's the default. Only write standalone: false if you need NgModule-based component.
- Q2: Can you still use NgModules in Angular 20?
- A: Yes, NgModules still work. Set standalone: false on components that need to be declared in modules.
- Q3: What imports do standalone components need?
- A: Declare dependencies in the imports array of @Component decorator - other components, directives, pipes.
- Q4: How do you provide services in standalone apps?
- A: Use providedIn: 'root' in services, or provide in app.config.ts providers array, or component providers array.
🔄 Before vs After v20
v14-18 (Explicit)
@Component({
selector: 'app-example',
standalone: true, // Required!
imports: [CommonModule],
template: '...'
})
export class ExampleComponent {}v20+ (Implicit) ✅
@Component({
selector: 'app-example',
// standalone: true is implicit!
imports: [CommonModule],
template: '...'
})
export class ExampleComponent {}🎯 This Component
Notice this component's decorator - there's no standalone: true!
@Component({
selector: 'app-standalone-default-demo',
changeDetection: ChangeDetectionStrategy.OnPush,
template: `...`
})
export class StandaloneDefaultDemoComponent {}In Angular 20+, this component is automatically standalone.
💻 Standalone by Default Examples
// ===== Angular 20+ Component (standalone by default) =====
import { Component } from '@angular/core';
@Component({
selector: 'app-my-component',
// No standalone: true needed!
imports: [SomeDirective, SomePipe],
template: `<p>Hello World!</p>`
})
export class MyComponent {}
// ===== Directive (also standalone by default) =====
@Directive({
selector: '[appHighlight]',
// No standalone: true needed!
})
export class HighlightDirective {}
// ===== Pipe (also standalone by default) =====
@Pipe({
name: 'myPipe',
// No standalone: true needed!
})
export class MyPipe implements PipeTransform {
transform(value: string): string {
return value.toUpperCase();
}
}
// ===== Opting OUT to use NgModule =====
@Component({
selector: 'app-legacy',
standalone: false, // Explicit opt-out!
template: `<p>I belong to a module</p>`
})
export class LegacyComponent {}
// Then declare in NgModule:
@NgModule({
declarations: [LegacyComponent],
exports: [LegacyComponent]
})
export class LegacyModule {}
// ===== Full Application Structure (v20+) =====
// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { App } from './app/app';
import { appConfig } from './app/app.config';
bootstrapApplication(App, appConfig);
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideHttpClient(),
// provideAnimations(),
// other providers...
]
};
// app.ts (root component)
@Component({
selector: 'app-root',
imports: [RouterOutlet, HeaderComponent, FooterComponent],
template: `
<app-header />
<router-outlet />
<app-footer />
`
})
export class App {}
// app.routes.ts
export const routes: Routes = [
{ path: '', component: HomeComponent },
{
path: 'feature',
loadComponent: () => import('./feature/feature').then(m => m.FeatureComponent)
}
];