Introduction to Angular signals

Key takeaway — A signal is a reactive value: when it changes, Angular knows exactly what to update in the interface, without re-reading the entire application the way Zone.js did.

Signals are the new way to handle reactivity in Angular (stable since Angular 17, enriched in Angular 18 and 19). They are progressively replacing the historical "Zone.js + global change detection" pairing with an explicit, fine-grained and performant system. In this course, you will learn them from scratch, with a live, runnable demo at every step that you can edit right in your browser.

What is a signal?

A signal is a container around a value that notifies interested consumers when that value changes. You read it by calling it like a function:

import { signal } from '@angular/core';

const compteur = signal(0); // creates a signal initialized to 0

console.log(compteur());     // read → 0
compteur.set(5);             // write → the value becomes 5
console.log(compteur());     // read → 5

Three ideas are enough to understand 90% of the model:

  1. Reading a signal means calling it: compteur().
  2. Writing to a writable signal: compteur.set(...) or compteur.update(...).
  3. Anything that reads a signal during its execution (a template, a computed, an effect) becomes automatically dependent on it and updates when it changes.

Why did Angular introduce signals?

The problem: global change detection

Historically, Angular uses Zone.js to detect when "something might have changed" (a click, a timer, an HTTP request). On every event, Angular re-checks the entire component tree to see what needs to be re-rendered. It is simple but expensive: on a large application, many things get recalculated needlessly.

The solution: fine-grained, explicit reactivity

With signals, Angular builds a dependency graph. When a signal changes, the framework knows precisely which views and which computations depend on it, and updates only those.

graph TD
    A[signal: prix] --> C[computed: total]
    B[signal: quantite] --> C
    C --> D[View: total display]
    A --> E[View: price display]

If only prix changes, Angular recomputes total and refreshes the two affected views — nothing else. This is what paves the way for "zoneless" applications (without Zone.js), lighter and faster, covered in chapter 8.

The three primitives to know

Primitive Role Mutable?
signal() Reactive source of truth ✅ via set / update
computed() Value derived from other signals ❌ read-only
effect() Side effect triggered by signals ❌ returns nothing

We dedicate a chapter to each. Here is a first glimpse bringing the three together:

import { signal, computed, effect } from '@angular/core';

const prix = signal(10);
const quantite = signal(2);

// Derived value: recomputed only when prix or quantite changes.
const total = computed(() => prix() * quantite());

// Side effect: re-runs on every change of total.
effect(() => console.log('New total:', total()));

prix.set(15); // triggers the recompute of total then the effect → logs "New total: 30"

Signals or RxJS: do you have to choose?

No — they are complementary. Signals excel at synchronous state that drives the display (a counter, a form, a selection). RxJS remains the best tool for asynchronous, event-driven streams (keystrokes with debounce, websockets, request orchestration). Chapter 7 shows how to make them talk to each other with toSignal() and toObservable().

What you will build

Throughout the chapters, you will write and run: a reactive counter, a cart with a computed total, a theme toggle, parent-child components communicating through signals, a stopwatch wired to RxJS, a task list, and finally a production-ready shared state service.

Prerequisites

  • Basics of Angular (component, template, data binding).
  • Notions of TypeScript (types, interfaces, arrow functions).
  • Angular 17+ installed (this course's demos target Angular 19).

In the next chapter, we get hands-on with the writable signal: creation, reading, set, update, and displaying it in a template.

We use Microsoft Clarity to understand how the site is used and improve it. By continuing to browse, you accept it. You can disable it at any time.