Angular
Angular is a complete, opinionated front-end framework maintained by Google and written in TypeScript. Where React is a UI library you combine with other tools, Angular ships the whole platform: components, a router, forms, an HTTP client, dependency injection, testing utilities, internationalization, a CLI, and server-side rendering. That consistency makes it popular for large enterprise applications and teams that value strong conventions.
Angular has changed substantially since version 14. Standalone components removed the need for NgModules, signals brought fine-grained reactivity, built-in control flow (@if, @for) replaced structural directives, and zoneless change detection, deferrable views, and incremental hydration improved performance. (AngularJS, the 2010 framework, is a different, end-of-life product.)
TL;DR
- Angular is a batteries-included TypeScript framework with a powerful CLI.
- Build with standalone components; no NgModules required.
- Use signals (
signal,computed,effect) for state; RxJS remains for async streams. - Templates use
@if,@for,@switch, property binding[x], event binding(y), and@defer. - Dependency injection provides services (
inject()), making code modular and testable. - Built-in router, reactive forms, HttpClient, and SSR with hydration.
Quick Example
A standalone component using signals, inject(), and the new control flow:
Core Concepts
Components and Templates
A component pairs a TypeScript class with a template and styles. Template syntax:
Inputs and outputs use the signal-based input(), output(), and model() functions in modern Angular.
Signals and RxJS
Signals hold values and notify dependents precisely: signal() for writable state, computed() for derived values, effect() for side effects, and linkedSignal/resource for state tied to other signals or async loading. RxJS observables remain central for HTTP, events, and complex async streams; toSignal and toObservable bridge the two.
Dependency Injection
Angular's DI container creates and supplies services. Use providedIn: "root" for app-wide singletons, provide services at component or route level for scoped instances, and swap implementations in tests. The inject() function works in constructors, fields, and factory functions.
Change Detection
Traditionally, Zone.js patched async APIs and triggered change detection across the component tree. With signals and OnPush components, Angular updates only what changed, and zoneless applications drop Zone.js entirely for better performance and simpler debugging.
Router, Forms, and HTTP
- Router — lazy-loaded routes (
loadComponent), guards and resolvers as functions, route parameters as inputs. - Forms — template-driven forms for simple cases; reactive forms (
FormGroup,FormControl, typed forms, validators) for complex validation. See Forms & Validation. - HttpClient — typed requests, interceptors for auth headers, retries, and error handling.
Rendering Options
Angular supports client-side rendering, server-side rendering with hydration, static prerendering, and incremental hydration with @defer blocks, configured through the CLI.
Best Practices
Start With the Angular CLI
ng new, ng generate, and ng update enforce conventions and automate migrations between major versions.
Use Standalone Components and Signals
They're the modern default: less boilerplate, clearer dependencies, and fine-grained updates.
Adopt OnPush or Zoneless Change Detection
Combined with signals and immutable inputs, it keeps large apps fast.
Keep Components Thin
Put data access and business logic in injectable services; components handle presentation and user interaction.
Manage Subscriptions
Prefer toSignal, the async pipe, or takeUntilDestroyed() so subscriptions end automatically.
Update Regularly
Angular releases a major version roughly every six months with automated migrations. Falling several versions behind makes upgrades much harder.
Common Mistakes
Memory Leaks From Manual Subscriptions
subscribe() without cleanup in long-lived components keeps listeners and memory alive.
Heavy Work in Templates
Calling functions in templates that do expensive work runs them on every change detection. Use computed() or pure pipes.
Overusing Shared Modules and Global Services
Everything provided in root makes dependencies unclear and bundles larger. Scope providers to routes where possible.
Nested Subscriptions
Subscribing inside subscribe callbacks causes race conditions. Use RxJS operators like switchMap and combineLatest.
Ignoring Bundle Size
Importing large libraries eagerly slows startup. Use lazy routes, @defer, and bundle budgets in angular.json.
Comparison
FAQ
What is Angular used for?
Building large, structured web applications — dashboards, enterprise tools, admin systems, and customer portals — where a consistent architecture and built-in tooling help big teams work together.
What's the difference between Angular and AngularJS?
AngularJS (1.x) is the original JavaScript framework, now end-of-life. Angular (2+) is a complete TypeScript rewrite with a different architecture.
Are signals replacing RxJS?
Signals handle synchronous state and reactivity in templates. RxJS remains valuable for async streams, HTTP, and complex event handling. Modern Angular uses both, with interop helpers.
Angular or React?
Choose Angular for an opinionated, all-in-one framework with strong conventions and TypeScript throughout. Choose React for flexibility, a larger ecosystem, and freedom to pick your own libraries.
Do I still need NgModules?
No. Standalone components, directives, and pipes are the default in modern Angular, though NgModules still work in existing apps.
Related Topics
- TypeScript — The language Angular is built on
- React — The most common alternative
- Vue — A lighter, progressive framework
- State Management — Signals, services, and stores
- Forms & Validation — Building robust forms