Angular Quick Reference
This reference condenses the syntax you reach for constantly once you already understand Angular's underlying concepts—control flow blocks, signal APIs, decorators, common CLI commands, and dependency injection patterns. It's meant for quick lookup mid-task, not first-time learning; each item links conceptually back to the deeper topic that explains why it works the way it does.
Cricket analogy: This is like a cricket coach's laminated cheat-sheet of field settings and DRS signals kept in the dugout: not where you learn the game, but a fast reminder once you already know why a leg-slip works.
Template Control Flow
The built-in control-flow syntax (@if, @for, @switch), stable since Angular 17, replaces the structural directives *ngIf/*ngFor/*ngSwitch for new code, offering better type narrowing and, for @for, a mandatory track expression that improves rendering performance by helping Angular identify which DOM nodes correspond to which data items across re-renders.
Cricket analogy: @if/@for/@switch are like the DRS replacing on-field umpire-only calls: the new built-in review process (stable since a fixed rule change) works better than the old *ngIf-style manual calls, and @for's mandatory track expression is like requiring a player's shirt number so the third umpire can track the same fielder across replays.
@if (user(); as u) {
<p>Welcome, {{ u.name }}</p>
} @else if (isLoading()) {
<p>Loading...</p>
} @else {
<p>Please sign in.</p>
}
@for (item of items(); track item.id) {
<li>{{ item.name }}</li>
} @empty {
<li>No items found.</li>
}
@switch (status()) {
@case ('active') { <span>Active</span> }
@case ('paused') { <span>Paused</span> }
@default { <span>Unknown</span> }
}Signals API at a Glance
signal(initialValue) creates writable reactive state; read it by calling it as a function. computed(fn) derives a read-only value that recalculates automatically when a dependency changes. effect(fn) runs a side effect whenever a signal it reads changes. input(), input.required(), and model() (for two-way binding) are the signal-based equivalents of @Input()/@Output().
Cricket analogy: signal() is like a scoreboard operator holding the current run total, callable anytime for the live number; computed() is the net-run-rate that auto-recalculates whenever the score or overs signal changes; effect() is the stadium announcer who shouts an update every time the total changes; input.required() is like a mandatory toss-call value a captain must provide before play starts.
import { Component, signal, computed, effect, input, model } from '@angular/core';
@Component({
selector: 'app-quantity',
standalone: true,
template: `<p>{{ quantity() }} x {{ unitPrice() }} = {{ total() }}</p>`,
})
export class QuantityComponent {
unitPrice = input.required<number>();
quantity = model(1); // two-way bindable: [(quantity)]="value"
total = computed(() => this.unitPrice() * this.quantity());
constructor() {
effect(() => console.log('Total is now', this.total()));
}
increment() {
this.quantity.update((q) => q + 1);
}
}Dependency Injection Shortcuts
The inject() function retrieves a dependency without constructor injection, useful in field initializers, functional guards, and interceptors. @Injectable({ providedIn: 'root' }) registers a service as an application-wide singleton without needing to list it in any providers array.
Cricket analogy: inject() is like a substitute fielder grabbing the team's spare ball directly from the umpire's pocket mid-over instead of waiting for it to be formally handed down the chain; @Injectable({providedIn:'root'}) is like the BCCI designating one official match ball supplier for every match nationwide without each stadium needing its own contract.
import { inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({ providedIn: 'root' })
export class UserService {
private http = inject(HttpClient);
getUser(id: string) {
return this.http.get(`/api/users/${id}`);
}
}
// Functional route guard using inject()
export const authGuard: CanActivateFn = () => {
const auth = inject(AuthService);
const router = inject(Router);
return auth.isLoggedIn() || router.parseUrl('/login');
};Frequently Used CLI Commands
ng new my-app scaffolds a new project; ng generate component my-thing (or ng g c my-thing) creates a standalone component with a spec file by default; ng serve runs the dev server with live reload; ng test runs the unit test suite via Karma; ng build produces a production-optimized static bundle; ng add <package> runs a schematic to install and wire up a library (e.g., ng add @angular/ssr).
Cricket analogy: ng new is like founding a brand-new franchise team from scratch for the IPL auction; ng g c is like drafting a specialist player (with a scouting report, the spec file); ng serve is like a live net-practice session with instant feedback; ng test is the team's fitness-testing lab (Karma) checking every player; ng build is preparing the final matchday squad sheet; ng add is like signing a ready-made analytics vendor (e.g. Hawk-Eye) that plugs straight into the setup.
Signal inputs (input()) and decorator-based @Input() can coexist in the same codebase during migration — Angular does not require an all-or-nothing switch. The ng generate @angular/core:signal-input-migration schematic can automate converting existing @Input() properties to the signal form.
- @if/@for/@switch are the modern built-in control-flow blocks; @for requires a track expression for performant re-rendering.
- signal(), computed(), and effect() form the core reactive primitives; call a signal as a function to read its current value.
- input(), input.required(), and model() are the signal-based counterparts to @Input()/@Output() with two-way binding support.
- inject() retrieves dependencies outside constructor injection, commonly used in functional guards, interceptors, and field initializers.
- @Injectable({ providedIn: 'root' }) is the standard way to register an app-wide singleton service without a providers array entry.
- ng generate, ng serve, ng test, ng build, and ng add cover the vast majority of day-to-day CLI usage.
Practice what you learned
1. What is required when using the @for control-flow block that was not required with *ngFor?
2. How do you read the current value of a signal called `count`?
3. What signal-based API supports two-way [(binding)] syntax, analogous to @Input() + @Output() pairs?
4. What does the inject() function allow that constructor injection does not as conveniently support?
5. What does @Injectable({ providedIn: 'root' }) achieve without any providers array entry?
Was this page helpful?
You May Also Like
The New Control Flow Syntax (@if, @for, @switch)
Explore Angular's built-in @if, @for, and @switch template control-flow blocks, introduced to replace *ngIf/*ngFor/*ngSwitch with faster, more ergonomic syntax.
Introduction to Signals
Understand Angular Signals — the reactive primitive that wraps a value and notifies dependents on change, forming the foundation of Angular's modern change-detection model.
The inject() Function
Learn how the inject() function offers a flexible alternative to constructor injection, and how it enables DI in functional contexts like guards, resolvers, and interceptors.
The Angular CLI
How the Angular CLI's ng commands generate code, run builds, and enforce consistent project structure across the development lifecycle.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics