Angular Cheat Sheet
Essential Angular cheat sheet covering CLI schematics, Signals, control flow syntax, dependency injection, routing, reactive forms, and RxJS integration.
1. Angular CLI & Workspace Setup
Commands for project initialization, build configurations, and schematics.
CLI Commands
npm install -g @angular/cli # Install CLI globally ng new my-app --ssr --style=scss # Create app with SSR and SCSS ng serve --open --port 4200 # Run dev server ng build --configuration production # Production bundle output to dist/ ng test # Execute unit tests ng e2e # Execute end-to-end tests ng update @angular/cli @angular/core # Automated workspace migration
Schematics Generators
ng g c features/user --standalone # Standalone Component ng g s services/auth # Injectable Service ng g p shared/pipes/truncate # Custom Pipe ng g d shared/directives/highlight # Custom Directive ng g g guards/auth # Functional Guard (CanActivate, CanMatch) ng g interceptor core/auth # Functional HTTP Interceptor ng g resolver resolvers/user-data # Route Data Resolver ng g environments # Generate environment.ts configuration files
2. Standalone Architecture & Signals API
Modern component configuration, Signal state primitives, and Signal inputs/outputs.
import { Component, signal, computed, effect, input, output, model, ChangeDetectionStrategy } from '@angular/core';
@Component({
selector: 'app-user-card',
standalone: true,
imports: [],
templateUrl: './user-card.component.html',
styleUrl: './user-card.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class UserCardComponent {
// Signal Inputs & Outputs
userId = input.required<string>(); // Required input signal
role = input<string>('guest'); // Input signal with default fallback
selected = model<boolean>(false); // Two-way binding signal input ([(selected)])
profileUpdated = output<UserProfile>(); // Output event emitter
// Writable & Computed Signals
count = signal<number>(0); // Writable signal state
doubleCount = computed(() => this.count() * 2); // Pure derived computed state
constructor() {
// Side Effects
effect((onCleanup) => {
const timer = setTimeout(() => console.log(this.count()), 1000);
onCleanup(() => clearTimeout(timer)); // Effect cleanup callback
});
}
mutateState() {
this.count.set(5); // Direct override
this.count.update(c => c + 1); // Value modification relative to prior state
}
}3. Built-in Control Flow
Native template control syntax (`@if`, `@for`, `@switch`).
@if (isLoggedIn()) {
<p>Welcome, {{ user().name }}</p>
} @else if (isPending()) {
<p>Authenticating...</p>
} @else {
<button (click)="login()">Sign In</button>
}
@for (item of items(); track item.id; let i = $index, count = $count) {
<div>{{ i + 1 }}/{{ count }}: {{ item.name }}</div>
} @empty {
<p>No items registered.</p>
}
@switch (userRole()) {
@case ('admin') { <app-admin-panel /> }
@case ('editor') { <app-editor-panel /> }
@default { <app-viewer-panel /> }
}4. Deferrable Views (`@defer`)
Declarative template lazy-loading with triggers.
@defer (on viewport; prefetch on idle) {
<app-heavy-chart [data]="chartData()" />
} @placeholder (minimum 500ms) {
<div class="skeleton">Chart Placeholder</div>
} @loading (after 100ms; minimum 1s) {
<app-spinner />
} @error {
<p>Failed to load component bundle.</p>
}
// Triggers: on idle, on viewport, on interaction,
// on hover, on timer(2s), when conditionSignal()5. Dependency Injection & Hierarchical Injectors
Services, functional `inject()`, InjectionTokens, and scoping.
import { Injectable, inject, InjectionToken, ApplicationConfig } from '@angular/core';
import { HttpClient } from '@angular/common/http';
export const API_CONFIG = new InjectionToken<ApiConfig>('API_CONFIG');
@Injectable({
providedIn: 'root' // Singleton service available application-wide
})
export class AuthService {
private config = inject(API_CONFIG); // Functional dependency injection
private http = inject(HttpClient);
}
// Provider Configurations in app.config.ts
export const appConfig: ApplicationConfig = {
providers: [
{ provide: API_CONFIG, useValue: { baseUrl: 'https://api.domain.com' } },
{ provide: LoggerService, useClass: CustomLoggerService }
]
};6. Routing, Functional Guards & Resolvers
Routes setup, route parameters, functional protection, and data resolvers.
import { Routes, CanActivateFn, ResolveFn, inject, Router } from '@angular/router';
export const authGuard: CanActivateFn = (route, state) => {
const auth = inject(AuthService);
const router = inject(Router);
return auth.isLoggedIn() ? true : router.parseUrl('/login');
};
export const userResolver: ResolveFn<UserData> = (route) => {
return inject(UserService).getUser(route.paramMap.get('id')!);
};
export const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{
path: 'dashboard',
loadComponent: () => import('./dashboard/dashboard.component').then(m => m.DashboardComponent),
canActivate: [authGuard]
},
{
path: 'user/:id',
loadComponent: () => import('./user/user.component').then(m => m.UserComponent),
resolve: { user: userResolver }
}
];7. Functional HTTP Interceptors
Intercept requests and responses within HTTP pipelines.
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const authToken = inject(AuthService).getToken();
const authReq = req.clone({
setHeaders: { Authorization: `Bearer ${authToken}` }
});
return next(authReq);
};8. Custom Directives
Host listeners and style bindings.
import { Directive, HostBinding, HostListener, input } from '@angular/core';
@Directive({ selector: '[appHighlight]', standalone: true })
export class HighlightDirective {
highlightColor = input<string>('yellow', { alias: 'appHighlight' });
@HostBinding('style.backgroundColor') bgColor = '';
@HostListener('mouseenter') onMouseEnter() {
this.bgColor = this.highlightColor() || 'yellow';
}
@HostListener('mouseleave') onMouseLeave() {
this.bgColor = '';
}
}9. Custom Pipes
Pure template data transformation.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'truncate', standalone: true, pure: true })
export class TruncatePipe implements PipeTransform {
transform(value: string, limit = 20, trail = '...'): string {
if (!value) return '';
return value.length > limit ? value.substring(0, limit) + trail : value;
}
}
// Usage: {{ text() | truncate:50:'...' }}10. Strictly Typed Reactive Forms
Typed form controls and built-in validators.
import { NonNullableFormBuilder, Validators } from '@angular/forms';
import { inject } from '@angular/core';
export class LoginForm {
private fb = inject(NonNullableFormBuilder);
form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(8)]]
});
onSubmit() {
if (this.form.valid) {
const rawData = this.form.getRawValue();
}
}
}11. RxJS & Signals Interoperability
Bridging RxJS Streams and Signals.
import { toSignal, toObservable } from '@angular/core/rxjs-interop';
import { signal, inject } from '@angular/core';
// Convert Observable to Signal
usersSignal = toSignal(this.userService.getUsers(), { initialValue: [] });
// Convert Signal to Observable
searchTerm = signal('');
searchTerm$ = toObservable(this.searchTerm);12. Projection & Query Signals
`viewChild`, `contentChild`, and multi-slot projection.
<!-- Modal Template -->
<div class="modal">
<ng-content select="[header]" />
<ng-content /> <!-- Default Body Slot -->
</div>
// TS Component Class Query Signals
header = viewChild<ElementRef>('header');
children = viewChildren(ChildComponent);
projected = contentChild(TemplateRef);13. Lifecycle Hooks & Cleanups
Execution phases and functional cleanup hooks.
ngOnInit() # Executed after input bindings setup
ngOnChanges(c) # Executed when input properties change
ngAfterViewInit() # Executed after view initialization
ngOnDestroy() # Executed before component destruction
// Functional cleanup with DestroyRef
private destroyRef = inject(DestroyRef);
constructor() {
const sub = stream$.subscribe();
this.destroyRef.onDestroy(() => sub.unsubscribe());
}14. State Management (Signal Store Pattern)
Reactive central state management with Signals.
import { Injectable, signal, computed } from '@angular/core';
export interface CartItem { id: string; price: number; quantity: number; }
@Injectable({ providedIn: 'root' })
export class CartStore {
private itemsSignal = signal<CartItem[]>([]);
readonly items = this.itemsSignal.asReadonly();
readonly itemCount = computed(() => this.itemsSignal().reduce((acc, i) => acc + i.quantity, 0));
readonly totalPrice = computed(() => this.itemsSignal().reduce((acc, i) => acc + i.price * i.quantity, 0));
addItem(newItem: CartItem) {
this.itemsSignal.update(items => {
const existing = items.find(i => i.id === newItem.id);
return existing
? items.map(i => i.id === newItem.id ? { ...i, quantity: i.quantity + 1 } : i)
: [...items, newItem];
});
}
removeItem(id: string) {
this.itemsSignal.update(items => items.filter(i => i.id !== id));
}
}15. SSR & Event Hydration
Configure Client Hydration and Fetch API for server render.
import { bootstrapApplication, provideClientHydration, withEventReplay } from '@angular/platform-browser';
import { provideHttpClient, withFetch } from '@angular/common/http';
bootstrapApplication(AppComponent, {
providers: [
provideClientHydration(withEventReplay()),
provideHttpClient(withFetch())
]
});16. Security & DomSanitizer
XSS prevention and DOM sanitization.
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { inject } from '@angular/core';
export class SecureComponent {
private sanitizer = inject(DomSanitizer);
trustedHtml: SafeHtml = '';
setUntrustedContent(rawHtml: string) {
this.trustedHtml = this.sanitizer.sanitize(SecurityContext.HTML, rawHtml) || '';
}
}17. Unit Testing (`TestBed`)
Testing Standalone components and service mocks.
import { TestBed } from '@angular/core/testing';
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [UserProfileComponent],
providers: [{ provide: UserService, useValue: spy }]
}).compileComponents();
});18. Legacy `NgModule` Structure
Module declarations for non-standalone codebases.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
declarations: [LegacyComponent],
imports: [CommonModule],
exports: [LegacyComponent]
})
export class LegacyModule {}