Angular Pocket Book — Uplatz
Standalone components • Signals & RxJS • Routing & guards • Forms • Testing • Build & deploy
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>
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();
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.
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.
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
).