Skip to content

Angular Signals

Posted on:January 17, 2024 at 12:29 AM

tp.web.random_picture

Notes on Angular Signals.

Table of contents

Open Table of contents

Introduction

Signals provide a new way for our code to tell our templates (and other code) that our data has changed. It improves Angular’s change detection and makes our code more reactive.

Observe the following example where z will not react to changes in x or y.

let x = 5;
let y = 3;
let z = x + y;

console.log(z); // => 8

x = 10;

console.log(z); // => 8

One of the reasons, we use frameworks/libraries like Angular or React is that we want a reactive user interface. We want to react to changes.

For example, when user changes quantity for an item added into the cart, we want the code to react and recalculate the cart total.

Current options to react to such changes are creating Getters or Custom Events. However, this works in the same component.

// Getter.
// When the quantity changes the change detection kicks in
// and the template gets the new extended price.
item = "Product XYZ";
price = 19416.13;
quantity = 1;

get exPrice() {
	return price * quantity;
}
// Event
item = "Product XYZ";
price = 19416.13;
quantity = 1;
exPrice = price;

onQuantitySelected(qty: number) {
	exPrice = price * quantity;
}

What if we want the updated price in a different component? That’s where signals comes in!

// Signals
item = "Product XYZ";
price = 19416.13;

// 'quantity' is marked as a signal.
quantity = signal(1);

// Here, computed signal reacts and recalculates 'exPrice'
// when the 'quantity' signal changes.
exPrie = computed(() => this.price * this.quantity());

Here is our rewritten first example using signals.

const x = signal(5);
const y = signal(3);
const z = computed(() => x() + y());

console.log(z()); // 8

x.set(10);

console.log(z()); // 13

Create a Signal

quantity = signal<number>(1);
// Examples

qtyAvailable = signal([1, 2, 3, 4, 5, 6]);

selectedVehicle = signal<Vehicle>({ id: 1, name: "Hector", price: 19234.13 });

vehciles = signal<Vehicle[]>([]);

Read a Signal

We read a signal by calling its getter function. Below are some examples.

constructor() {
	console.log(this.quantity());
}
<option *ngFor="let q of qtyAvailable()">{{ q }}</option>
<div>Vehicle: {{ selectedVehicle().name }}</div>
<div>Price: {{ selectedVehicle().price }}</div>

Set / Update a Signal

// Replace the value.
this.quantity.set(qty);
// Update the value based on the current value.
this.quantity.update(qty => qty * 2);

Computed Signal

totalPrice = computed(() => this.price() * this.quantity());
// Here,
// `computed` is a creation function.
// arrow function is a computation function.

Effect for Side Effects

Use an effect if you want to run some code when a signal changes.

effect(() => console.log(this.selectedVehicle()));

References