Angular Signals
Angular Signals, introduced in Angular 16, are a new reactivity model built into the Angular core package (@angular/core). They provide a lightweight, fine-grained reactive system that works without Zone.js, enabling better performance and easier state tracking.
Think of Signals as reactive variables that notify when their values change, similar to BehaviorSubject, computed, or useState in other frameworks.
Use of Signals
- No need for manual RxJS subscription management.
- Fully integrates with Angular’s rendering engine.
- Enables Zoneless and fine-grained change detection.
- Cleaner, simpler reactive state in components.
Setup
If you are using Angular 16 or later, Signals are built-in with @angular/core. Just start using them; there is no extra package needed.
Counter with Computed Signals
To create a counter, we can use signals:
- signal: to hold state
- computed: to derive new values
- effect: to log or trigger side effects
Component
// counter.component.ts
import { Component, computed, effect, signal } from '@angular/core';
@Component({
selector: 'app-counter',
templateUrl: './counter.component.html',
styleUrls: ['./counter.component.css'],
})
export class CounterComponent {
count = signal(0);
doubleCount = computed(() => this.count() * 2);
constructor() {
effect(() => {
console.log(`Count changed to ${this.count()}`);
});
}
increment() {
this.count.set(this.count() + 1);
}
decrement() {
this.count.set(this.count() - 1);
}
reset() {
this.count.set(0);
}
}
HTML Template
<!-- counter.component.html -->
<div class="counter-card">
<h2>Counter: {{ count() }}</h2>
<p>Double: {{ doubleCount() }}</p>
<button (click)="increment()">Increment</button>
<button (click)="decrement()">Decrement</button>
<button (click)="reset()">Reset</button>
</div>
Key Signal APIs
Function |
Description |
signal(initialValue) |
Creates a reactive signal |
computed(() => ...) |
Creates a derived signal |
effect(() => ...) |
Runs side-effect when the signal changes |
set(), update() |
Update signal values |
WritableSignal vs ReadonlySignal
const name = signal('Cynthia');
name.set('Vikas'); // writable
const age = computed(() => 2025 - 1995);
// age.set(...) Not allowed because it is readonly
Signals are great for local component state, but RxJS is still useful for:
- Event streams
- Backend streams
- Complex data pipelines
- Forms, HTTP, and NgRx integrations
Benefits of using Signals
- Better performance: No Zone.js required
- Cleaner templates: Access values directly via signal()
- Automatic cleanup: No need to unsubscribe()
- Fine-grained updates: Only affected DOM elements re-render
Conclusion
Angular Signals bring a modern, powerful, and ergonomic reactive system to Angular applications. They are used for
- local state management.
- Easy to use and understand.
- Highly performant for large applications.