Standalone Components ๐๏ธ
Standalone components are Angularโs default and recommended approach for building modern applications! Think of them as independent LEGO blocks that donโt need a big box (NgModule) to organize them. Theyโre now the standard way to build Angular apps - simpler, more modular, and future-ready!
๐ฏ What are Standalone Components?
Section titled โ๐ฏ What are Standalone Components?โStandalone components are Angular components that work independently without NgModules. They manage their own dependencies and can be imported directly where needed.
Why Standalone is Now the Standard:
- ๐ฏ Default by Design - New Angular projects use standalone by default
- ๐ซ No NgModules - Skip the module boilerplate entirely
- ๐ฆ Direct Imports - Import exactly what you need, where you need it
- ๐ณ Better Tree Shaking - Smaller bundles with unused code elimination
- โก Simpler Architecture - Less complexity, easier to understand
- ๐ Easy Migration - Can coexist with existing NgModule components
- ๐ Angularโs Future - The official direction for all new development
import { Component } from '@angular/core';import { CommonModule } from '@angular/common';import { FormsModule } from '@angular/forms';
@Component({ selector: 'app-user-profile', standalone: true, // โ
Default in new Angular projects imports: [CommonModule, FormsModule], // Direct imports template: ` <div class="profile"> <h1>{{ user.name }}</h1> <input [(ngModel)]="user.email" placeholder="Email"> <button (click)="save()">Save</button> </div> `})export class UserProfileComponent { user = { name: 'John Doe', email: 'john@example.com' };
save() { console.log('Saving user:', this.user); }}๐ Legacy vs Modern Angular
Section titled โ๐ Legacy vs Modern Angularโโ Legacy Approach (NgModules)
Section titled โโ Legacy Approach (NgModules)โ// user.module.ts - Extra boilerplate file@NgModule({ declarations: [UserProfileComponent], imports: [CommonModule, FormsModule], exports: [UserProfileComponent]})export class UserModule { }
// app.module.ts - Complex module configuration@NgModule({ imports: [UserModule], // Import entire module // ...})export class AppModule { }โ Modern Angular (Standalone - Default)
Section titled โโ Modern Angular (Standalone - Default)โ// Just import the component directly - no modules needed!import { UserProfileComponent } from './user-profile.component';
@Component({ standalone: true, // Default in new projects imports: [UserProfileComponent], // Direct import template: `<app-user-profile></app-user-profile>`})export class AppComponent { }๐ฏ Angular CLI Default Behavior
Section titled โ๐ฏ Angular CLI Default BehaviorโNew Angular projects now generate standalone components by default!
# Create a new Angular project (standalone by default)ng new my-app
# Generate a new component (automatically standalone)ng generate component user-profile# Creates: user-profile.component.ts with standalone: true
# Generate a new project with explicit standalone flagng new my-app --standaloneGenerated component structure:
// Automatically generated with standalone: true@Component({ selector: 'app-user-profile', standalone: true, imports: [CommonModule], templateUrl: './user-profile.component.html', styleUrl: './user-profile.component.css'})export class UserProfileComponent { }๐ Common Patterns
Section titled โ๐ Common Patternsโ1. Basic Standalone Component
Section titled โ1. Basic Standalone Componentโ@Component({ selector: 'app-counter', standalone: true, template: ` <div> <p>Count: {{ count }}</p> <button (click)="increment()">+</button> <button (click)="decrement()">-</button> </div> `})export class CounterComponent { count = 0;
increment() { this.count++; } decrement() { this.count--; }}2. Standalone with Services
Section titled โ2. Standalone with Servicesโ@Injectable({ providedIn: 'root' })export class UserService { getUsers() { return ['Alice', 'Bob', 'Charlie']; }}
@Component({ selector: 'app-user-list', standalone: true, imports: [CommonModule], template: ` <ul> @for (user of users; track user) { <li>{{ user }}</li> } </ul> `})export class UserListComponent { users = inject(UserService).getUsers();}3. Standalone with Child Components
Section titled โ3. Standalone with Child Componentsโ@Component({ selector: 'app-user-card', standalone: true, template: ` <div class="card"> <h3>{{ user.name }}</h3> <p>{{ user.email }}</p> </div> `, inputs: ['user']})export class UserCardComponent { user!: { name: string; email: string };}
@Component({ selector: 'app-dashboard', standalone: true, imports: [CommonModule, UserCardComponent], // Import child component template: ` <div class="dashboard"> <h2>User Dashboard</h2> @for (user of users; track user.id) { <app-user-card [user]="user"></app-user-card> } </div> `})export class DashboardComponent { users = [ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' } ];}4. Standalone Routing
Section titled โ4. Standalone Routingโexport const routes: Routes = [ { path: 'users', loadComponent: () => import('./user-list.component').then(c => c.UserListComponent) }, { path: 'profile', loadComponent: () => import('./user-profile.component').then(c => c.UserProfileComponent) }];
// main.tsbootstrapApplication(AppComponent, { providers: [ provideRouter(routes), // โ
No RouterModule needed provideHttpClient() // โ
No HttpClientModule needed ]});โ Best Practices
Section titled โโ Best Practicesโ1. Import What You Need
Section titled โ1. Import What You Needโ// โ
Good - Import specific modules@Component({ standalone: true, imports: [CommonModule, FormsModule, RouterModule], // ...})
// โ Avoid - Don't create unnecessary modules@NgModule({ imports: [CommonModule, FormsModule], exports: [CommonModule, FormsModule]})export class SharedModule { } // Not needed with standalone!2. Use Providers Array
Section titled โ2. Use Providers Arrayโ// โ
Good - Provide services directly@Component({ standalone: true, providers: [UserService], // Component-level service // ...})
// โ
Better - Use providedIn: 'root' for global services@Injectable({ providedIn: 'root' })export class UserService { }3. Organize Imports
Section titled โ3. Organize Importsโ// โ
Good - Group imports logically@Component({ standalone: true, imports: [ // Angular modules CommonModule, FormsModule, RouterModule,
// Your components UserCardComponent, LoadingSpinnerComponent ], // ...})๐ฏ Quick Checklist
Section titled โ๐ฏ Quick Checklistโ- Add
standalone: trueto your component decorator - Import necessary modules in the
importsarray - Remove component from NgModule declarations
- Import the component directly where needed
- Use
loadComponentfor lazy loading - Provide services using
providedIn: 'root'or component providers
๐ Next Steps
Section titled โ๐ Next Stepsโ- Angular Signals - Modern reactivity with standalone components
- Computed Signals - Derived state in standalone apps
- Control Flow - New template syntax with standalone components
Remember: Standalone components are now Angularโs default and standard approach! All new projects use them automatically. If youโre working with legacy NgModule projects, consider migrating to enjoy the benefits of simpler, more modular code! ๐