Angular Cheat Sheet
A practical reference covering Angular CLI commands, standalone components, core decorators, and dependency injection for building single-page applications.
Angular CLI Commands
Common commands for scaffolding and running an Angular project.
ng new my-app # scaffold a new projectng serve # dev server with live reloadng generate component my-component # shorthand: ng g c my-componentng generate service my-service # shorthand: ng g s my-serviceng build --configuration production # production buildng test # run unit testsng add @angular/material # add and configure a library
Standalone Component
A modern standalone component with template directives.
import { Component } from '@angular/core';@Component({ selector: 'app-hello', standalone: true, template: ` <h1>{{ title }}</h1> <ul> <li *ngFor='let item of items'>{{ item.name }}</li> </ul> <input [(ngModel)]='search' /> <button (click)='increment()'>+1</button> `,})export class HelloComponent { title = 'Hello Angular'; items = [{ name: 'One' }, { name: 'Two' }]; search = ''; count = 0; increment() { this.count++; }}
Core Decorators
The decorators you will use in almost every Angular app.
- @Component- marks a class as an Angular component and attaches a template/selector
- @Injectable- marks a class as available for dependency injection, typically a service
- @Input- declares a property that can receive data bound from a parent component
- @Output- declares an EventEmitter a component uses to emit events to its parent
- @NgModule- (legacy) groups components, directives and providers into a module; optional with standalone APIs
- @HostListener- binds a class method to a DOM event fired on the component's host element
Services & Dependency Injection
Defining an injectable service and consuming it with inject().
import { Injectable, inject } from '@angular/core';import { HttpClient } from '@angular/common/http';@Injectable({ providedIn: 'root' })export class DataService { private http = inject(HttpClient); getUsers() { return this.http.get('/api/users'); }}// consuming the service in a componentexport class UsersComponent { private dataService = inject(DataService);}
Signals: State, Computed & Effects
Angular's fine-grained reactivity primitive as an alternative to zone.js-based change detection.
import { Component, signal, computed, effect } from '@angular/core';@Component({ selector: 'app-counter', standalone: true, template: ` <p>{{ count() }} (doubled: {{ doubled() }})</p> <button (click)="increment()">+1</button> `,})export class CounterComponent { count = signal(0); doubled = computed(() => this.count() * 2); constructor() { // effect() re-runs whenever any signal it reads changes effect(() => { console.log(`count changed to ${this.count()}`); }); } increment() { this.count.update(n => n + 1); // or this.count.set(n) }}
Functional Route Guards & HTTP Interceptors
Modern function-based guards and interceptors replacing class-based ones, using inject() for dependencies.
import { inject } from '@angular/core';import { CanActivateFn, Router } from '@angular/router';import { HttpInterceptorFn } from '@angular/common/http';export const authGuard: CanActivateFn = (route, state) => { const auth = inject(AuthService); const router = inject(Router); return auth.isLoggedIn() ? true : router.parseUrl('/login');};// route config// { path: 'admin', component: AdminComponent, canActivate: [authGuard] }export const authInterceptor: HttpInterceptorFn = (req, next) => { const auth = inject(AuthService); const cloned = req.clone({ setHeaders: { Authorization: `Bearer ${auth.token()}` }, }); return next(cloned);};// provideHttpClient(withInterceptors([authInterceptor]))
Change Detection & Performance
Concepts for keeping Angular apps fast as component trees grow.
- ChangeDetectionStrategy.OnPush- skips checking a component's subtree unless an @Input reference changes, an event fires inside it, or a signal it reads updates
- trackBy- in *ngFor, gives Angular a stable key function so it patches existing DOM nodes instead of destroying/recreating them on array changes
- Signals vs. zone.js- signals notify Angular exactly which components depend on changed state, moving toward zoneless change detection instead of the global zone.js dirty-check
- Pure pipes- pipes are pure by default, re-executing only when their input reference changes, cheaper than calling a method in the template
- ChangeDetectorRef.markForCheck()- manually flags an OnPush component for the next check cycle, needed when state changes outside Angular's normal event handling
- detach() / reattach()- fully removes a component from the change detection tree for manual, imperative control in performance-critical views
Reactive Forms with Validators
Building a typed form group with built-in and custom validators.
import { FormBuilder, Validators, AbstractControl } from '@angular/forms';import { inject } from '@angular/core';function matchesPassword(control: AbstractControl) { const group = control.parent; if (!group) return null; return group.get('password')?.value === control.value ? null : { mismatch: true };}export class SignupComponent { private fb = inject(FormBuilder); form = this.fb.group({ email: ['', [Validators.required, Validators.email]], password: ['', [Validators.required, Validators.minLength(8)]], confirmPassword: ['', [Validators.required, matchesPassword]], }); submit() { if (this.form.invalid) { this.form.markAllAsTouched(); return; } console.log(this.form.value); }}
RxJS in Services & the async Pipe
Composing reactive streams in a service and consuming them declaratively in a template.
import { Injectable, inject } from '@angular/core';import { HttpClient } from '@angular/common/http';import { combineLatest, switchMap, debounceTime, distinctUntilChanged } from 'rxjs';import { BehaviorSubject } from 'rxjs';@Injectable({ providedIn: 'root' })export class SearchService { private http = inject(HttpClient); private query$ = new BehaviorSubject(''); results$ = this.query$.pipe( debounceTime(300), distinctUntilChanged(), switchMap(q => this.http.get(`/api/search?q=${q}`)) // cancels the previous in-flight request ); search(term: string) { this.query$.next(term); }}// template: <div *ngFor="let r of searchService.results$ | async">{{ r.title }}</div>// the async pipe auto-subscribes and auto-unsubscribes on destroy
Standalone components have been the default since Angular 17 -- prefer them over NgModule-based components to cut boilerplate, and use the inject() function instead of constructor injection inside functional guards and resolvers, where there is no constructor to inject into.