Angular Pocket Book

Angular Pocket Book — Uplatz

Standalone components • Signals & RxJS • Routing & guards • Forms • Testing • Build & deploy

Section 1 — Fundamentals

1) What is Angular?

Angular is a TypeScript-based framework for building scalable SPAs. It features a component-first architecture, dependency injection, powerful routing, reactive forms, and built-in tooling (CLI, builder, test runner). Since v16+, apps can be built with standalone components (no NgModules) and signals for fine-grained reactivity.

# Create a new project
npm install -g @angular/cli
ng new shop --standalone --routing --style=scss
cd shop && ng serve -o

2) Component Anatomy

A component couples template, styles, and logic. With standalone, you declare standalone: true and import needed features in the metadata.

import { Component } from '@angular/core';
@Component({
  selector: 'app-hello',
  standalone: true,
  template: `<h1>Hello {{name}}</h1>`,
})
export class HelloComponent { name = 'Angular'; }

3) Dependency Injection (DI)

Services are injected through constructors. Provide at root for singletons or at component for scoped instances.

import { Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class Api { getProducts() { /* http */ } }

4) Signals (Reactive State)

signals are reactive primitives that track reads/writes without heavy change detection. Use signal(), computed(), and effect().

import { signal, computed, effect } from '@angular/core';
const count = signal(0);
const doubled = computed(() => count() * 2);
effect(() => console.log('count =', count()));

5) RxJS Basics

For async streams (HTTP, events), Angular leans on RxJS. Use Observable, pipe(), and operators like map, switchMap, catchError. Prefer the async pipe to manage subscriptions in templates.

<div *ngIf="products$ | async as products">{{ products.length }} items</div>

Section 2 — Routing, Forms & HTTP

6) Standalone Routing

Define routes with Routes and bootstrap using provideRouter(). Lazy load features with loadComponent or loadChildren.

import { Routes } from '@angular/router';
export const routes: Routes = [
  { path: '', loadComponent: () => import('./home.component').then(m => m.HomeComponent) },
  { path: 'product/:id', loadComponent: () => import('./product.component').then(m => m.ProductComponent) },
];

7) Route Guards

Protect routes with canActivate/canMatch guards that return boolean/UrlTree/Observable.

import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
export const authGuard: CanActivateFn = () => {
  const router = inject(Router);
  const loggedIn = /* check auth */;
  return loggedIn || router.parseUrl('/login');
};

8) Reactive Forms

Use FormGroup, FormControl, and validators. Works well for complex validation and dynamic forms.

form = new FormGroup({
  email: new FormControl('', { nonNullable:true }),
  qty: new FormControl(1)
});

9) Template-Driven Forms

Simpler forms using directives like ngModel. Good for small forms; for scale, prefer reactive.

<input name="email" [(ngModel)]="email" required />

10) HTTP Client

Use HttpClient for REST. Interceptors add headers, auth, or error handling globally.

this.http.get<Product[]>('/api/products').subscribe();

Section 3 — Architecture, State & UI

11) State Management

For local UI state use signals; for app-wide state use services + signals or libraries (NgRx, NGXS, Akita). Keep state immutable and derive with selectors/computed.

12) Reusable UI

Use Angular Material, CDK, Tailwind, or design systems. Prefer standalone components and feature folders (e.g., features/, shared/).

ng add @angular/material

13) Signals + RxJS Together

Convert Observables to signals with toSignal(), and signals to Observables with toObservable() for interop.

14) Performance

  • Prefer *ngFor; trackBy to avoid re-render churn.
  • Use OnPush change detection where possible.
  • Route-based code splitting and preloading strategies.

Section 4 — Testing, Build & Deploy

15) Unit & Component Testing

Use TestBed for components; mock providers; test pure logic separately. For e2e, use Playwright or Cypress.

import { TestBed } from '@angular/core/testing';
import { HelloComponent } from './hello.component';
beforeEach(() => TestBed.configureTestingModule({ imports:[HelloComponent] }));

16) Build & Deploy

ng build --configuration production outputs static assets in dist/. Host via any static host (S3+CloudFront, Firebase Hosting, Netlify). Ensure correct baseHref when served from a subpath.

ng build --configuration production --base-href /app/

17) Environments & Config

Use Angular’s built-in file replacements or load JSON at runtime (e.g., via APP_INITIALIZER) for 12-factor compatibility across environments.

18) Common Pitfalls

  • Memory leaks from forgotten subscriptions (prefer async pipe).
  • Heavy components; split into smaller presentational/containers.
  • Blocking main thread with expensive computations; offload to Web Workers.

Section 5 — Quick Q&A

19) Interview Q&A — 8 Quick Ones

1) Standalone vs NgModules? Standalone simplifies setup/imports; NgModules still supported for legacy/large libs.

2) Signals vs RxJS? Signals for local reactive state; RxJS for async streams and effects. They interoperate.

3) Change detection strategies? Default vs OnPush. OnPush rechecks only on input/reference change or signals.

4) Lazy loading? Use loadComponent/loadChildren in routes; reduces initial bundle size.

5) Form choice? Template-driven for simple forms; Reactive for complex validation and scalability.

6) HTTP best practices? Interceptors for auth/retry; types for responses; handle errors centrally.

7) Styling? View encapsulation by default; use Tailwind/Material; prefer utility classes for consistency.

8) Deployment? Build static assets, serve via CDN, set correct cache headers, and handle SPA fallback (rewrite to index.html).