Signals
A signal is a wrapper around a value that can notify interested consumers when that value changes. Because Angular Signals granularly track how and where your state is used throughout an application, the framework can optimize rendering updates.
As Angular must be able to detect changes of the signal value, it must be immutable.
- Video In-depth Angular Signals, mental models for reactive graph, push / pull, laziness and more! π₯ by Tomas Trajan.
- Signals have an effect on change detection in Angular. Refer to the dedicated section about change detection to learn more about this.
- Blog Post Signals are VALUES, not EVENTS by Tomasz Ducin
- Blog Post Component Communication with Signals by Manfred Steyer
Signal functionsβ
signal()
- stable since 17.0β
Creates a writeable signal, that can be updated using x.set()
or x.update()
methods.
const counter = signal(0);
counter.set(2);
counter.update(count => count + 1);
computed()
- stable since 17.0β
Memoizing signal, which calculates its value from the values of other signals. A computed signal is not writable. Note that it is not allowed writing to signals in a computed
by default. This is a safety facility that no cycles are created.
const counter = signal(0);
// Automatically updates when `counter` changes:
const isEven = computed(() => counter() % 2 === 0);
effect()
- developer preview since 17.0β
Get notified when signals have changed their value. The effect()
function can only be used in an injection context. Note that it is not allowed writing to signals in a effect
by default. This is a safety facility that no cycles are created. If you really want to write signals, set allowSignalWrites
in the CreateEffectOptions
.
const counter = signal(0);
effect(() => console.log('The counter is:', counter()));
// The counter is: 0
counter.set(1);
// The counter is: 1
input()
- developer preview - since 17.1β
Signal input is a signal-based alternative to the traditional @Input
decorator
@Component({
template: `<h1>Counter value: {{ value() }}</h1>`,
})
export class Component {
// returns Signal<number>
value = input(0);
// returns Signal<string>
firstName = input.required<string>();
// returns Signal<string | undefined>
lastName = input<string>();
}
- Angular Blog Post Signal Input is now available in developer preview by Paul Gschwendtner
- Blog Post Angular Signal Inputs are here to change the game π² by Enea
- Blog Post Angular Signal Inputs by Kevin Kreuzer
Signal queries - developer preview since 17.2β
Signal queries are a signal-based alternative to the traditional @ViewChild
, @ViewChildren
, @ContentChild
or @ContentChildren
decorator
import {contentChild, contentChildren, viewChild, viewChildren} from '@angular/core';
@Component({
template: `
<div #el>element to query</div>
<ng-content></ng-content>
`
})
export class Component {
// returns Signal<ElementRef<HTMLDivElement> | undefined>
divEl = viewChild<ElementRef<HTMLDivElement>>('el');
// returns Signal<ElementRef<HTMLDivElement>>
divElRequired = viewChild.required<ElementRef<HTMLDivElement>>('el');
// returns Signal<ReadonlyArray<ElementRef<HTMLDivElement>>>
divEls = viewChildren<ElementRef<HTMLDivElement>>('el');
// returns Signal<TestComponent | undefined>
testComponent = contentChild(TestComponent);
// returns Signal<TestComponent>
testComponentRequired = contentChild.required(TestComponent);
// returns Signal<ReadonlyArray<TestComponent>>
testComponents = contentChildren(TestComponent)
}
model()
signals - developer preview since 17.2β
Model signals are exposed as input/output pair to be used by the parent component.
@Component({
selector: 'custom-checkbox',
template: `
<div class="cool-checkbox-treatment">
<input type="checkbox" (click)="toggle()" [value]="checked()">
</div>
`
})
export class CustomCheckbox {
checked = model(false); // returns ModelSignal<number>
toggle() {
this.checked.set(!this.checked());
}
}
- Blog Post Model Inputs: Reactive Two-Way Binding
output()
function - developer preview since 17.3β
output()
allows you to define our components output similar to input()
.
@Component({
selector: 'custom-checkbox',
template: `
<div class="cool-checkbox-treatment">
<input type="checkbox" (click)="checkedChange.emit(!checked())" [value]="checked()">
</div>
`
})
export class CustomCheckbox {
checked = input(false);
checkedChange = output<boolean>(); // returns OutputEmitterRef<boolean>
private nameChange$ = new Subject<string>(); // any observable
nameChange = outputFromObservable(this.nameChange$); // returns OutputEmitterRef<string>
checkedChangeEvents = outputToObservable(this.checkedChange); // returns Observable<boolean>
}
- Angular Blog Post Meet Angularβs new output() API by Paul Gschwendtner
NGRX SignalStoreβ
EnterJS Angular Day Presentation from Manfred Steyer
Standalone Store from the NGRX team built completely on top of Signals. It is lightweight and independent form the well known NGRX Store based on the Redux pattern.
Install using npm i @ngrx/signals
.
Debugging Signalsβ
The Angular Team is planning to add debugging capabilities for signals into the Angular Dev Tools.
Signal Formsβ
Because there is currently no support for signals in Forms, the community created ng-signal-forms
. This Blog Post is a nice introduction into this library.