Angular Signals
Angular signals are a reactive primitive that provides a new way to manage state in your applications. Signals offer fine-grained reactivity and improved performance over traditional change detection.
What are Signals?
Signals are a reactive wrapper around a value that notifies Angular when the value changes. When you read a signal’s value, Angular automatically tracks where it’s used, enabling efficient updates.
Signals are available in Angular 16+ and represent the future of reactive state management in Angular applications.
Creating Signals
Use the signal() function to create a signal with an initial value:
import { Component, signal } from '@angular/core';
@Component({
templateUrl: './hero-page.component.html'
})
export class HeroPageComponent {
name = signal('Ironman');
age = signal(45);
getHeroDescription() {
return `${this.name()} - ${this.age()}`;
}
}
Source: src/app/pages/hero/hero-page.component.ts:8-12
Reading Signal Values
To read a signal’s value, call it as a function. In templates, Angular automatically subscribes to signal changes:
<h1>{{ name() }}</h1>
<dl>
<td>Nombre:</td>
<dd>{{ name() }}</dd>
<td>Edad:</td>
<dd>{{ age() }}</dd>
<td>Método:</td>
<dd>{{ getHeroDescription() }}</dd>
<td>Capitalizado:</td>
<dd>{{ name().toUpperCase() }}</dd>
</dl>
Source: src/app/pages/hero/hero-page.component.html:1-16
Updating Signals
Signals provide two methods for updating values:
Using set()
Directly set a new value:
changeHero() {
this.name.set('spiderman');
this.age.set(22);
}
resetForm() {
this.name.set('Ironman');
this.age.set(45);
}
Source: src/app/pages/hero/hero-page.component.ts:13-23
Using update()
Update based on the current value:
import { Component, signal } from '@angular/core';
export class CounterPage {
counterSignal = signal(10);
incremento(value: number) {
this.counterSignal.update((current) => current + value);
}
resetContador() {
this.counterSignal.set(0);
}
}
Source: src/app/pages/counter/counter-page.ts:19-28
Signals with Arrays and Objects
For complex data structures, use update() to create new references:
interface Character {
id: number;
name: string;
power: number;
}
export class DragonballPage {
name = signal('');
power = signal(0);
characters = signal<Character[]>([
{ id: 1, name: 'Goku', power: 9001 },
]);
addCharacter() {
if (!this.name().trim() || this.power() <= 0) {
return;
}
const newCharacter: Character = {
id: this.characters().length + 1,
name: this.name(),
power: this.power(),
};
// Create new array reference to trigger reactivity
this.characters.update(chars => [...chars, newCharacter]);
}
}
Source: src/app/pages/dragonball/dragonball-page.ts:14-38
When working with arrays or objects in signals, always create a new reference using spread operators or array methods. Mutating the existing object won’t trigger updates.
Template Integration
In templates, signals are called as functions and Angular automatically tracks dependencies:
<h1>Counter: {{ counter }}</h1>
<h1>Counter Signal: {{ counterSignal() }}</h1>
<hr/>
<button (click)="incremento(1)">+1</button>
<button (click)="incremento(-1)">-1</button>
<button (click)="resetContador()">Reset</button>
Source: src/app/pages/counter/counter-page.html:1-6
Benefits of Signals
Key Advantages:
- Fine-grained reactivity - only components using the signal update
- Better performance with OnPush change detection
- Simpler state management without RxJS complexity
- Automatic dependency tracking in templates
- Type-safe updates with TypeScript
Signals vs Traditional Properties
Compare the traditional approach with signals:
export class CounterPage {
// Traditional property
counter = 10;
// Signal-based property
counterSignal = signal(10);
incremento(value: number) {
// Traditional update
this.counter += value;
// Signal update
this.counterSignal.update((current) => current + value);
}
}
Source: src/app/pages/counter/counter-page.ts:18-23
The signal approach provides reactive updates that work seamlessly with Angular’s change detection, especially when using OnPush strategy.
Next Steps
- Learn about Change Detection and how signals improve performance
- Explore Components to understand where signals fit in your architecture
- See Routing to manage navigation state with signals