In new Angular (19+) can I create linkedSignal that depends on two other signals? In the example
import { signal, linkedSignal } from '@angular/core';
const sourceSignal = signal(0);
const updatedSignal = linkedSignal({
source: sourceSignal,
computation: () => sourceSignal() * 5,
});
updatedSignal depends on sourceSignal.
Can I make it dependent on sourceSignal1 and sourceSignal2?
Ans: If you want to access the previous state of the linked signal, or to improve readability of the linked signal (if there are lot of source
signals you can use this pattern of source and computation
, else a plain signal will suffice. As per the documentation, the comments mention as follows:
linked_signal.ts - source code
Creates a writable signals whose value is initialized and reset by >the linked, reactive computation. This is an advanced API form where the computation has access to >the previous value of the signal and the computation result.
@developerPreview
Yes, you can specify either an array
or an object
as the return value of the source function.
The most important information to type the linked signal to the below interface:
export declare function linkedSignal<S, D>(options: {
source: () => S;
computation: (source: NoInfer<S>, previous?: {
source: NoInfer<S>;
value: NoInfer<D>;
}) => D;
equal?: ValueEqualityFn<NoInfer<D>>;
}): WritableSignal<D>;
and not:
export declare function linkedSignal<D>(computation: () => D, options?: {
equal?: ValueEqualityFn<NoInfer<D>>;
}): WritableSignal<D>;
is to add the typing to the linkedSignal
, the first type is the interface
of the object returned by the source
callback. The second is the type of the value returned by the linked signal.
updatedSignal = linkedSignal<TypedLinkedSignal, number>({ ... });
^ ^
interface of source callback | | return type of linked signal
Firstly we should define an interface, which contains the input signals that are used for the linked signal, this interface is necesssary so that we can strictly type the object that is used to trigger the reactivity of the linked signal.
export interface TypedLinkedSignal {
sourceSignal: number;
sourceSignal2: number;
}
We can return an object
whose properties are the individual items where the value is the executed signal.
Notice, that we can use the first
argument of the function of computation is the object we specified in source, but with the signals executed and the values ready for usage.
I have named the first argument as response
(you can name it anything) and use the values for the computation.
In the below example. We have two model
which are signals, we place then inside an object, which is returned by the source
callback. Finally we use the returned values to compute the linked signal.
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { model, linkedSignal } from '@angular/core';
import { FormsModule } from '@angular/forms';
export interface TypedLinkedSignal {
sourceSignal: number;
sourceSignal2: number;
}
@Component({
selector: 'app-root',
imports: [FormsModule],
template: `
<input [(ngModel)]="sourceSignal"/>
<input [(ngModel)]="sourceSignal2"/>
<input [ngModel]="updatedSignal()"/>
`,
})
export class App {
sourceSignal = model(0);
sourceSignal2 = model(0);
updatedSignal = linkedSignal<TypedLinkedSignal, number>({
source: () => ({
sourceSignal: this.sourceSignal(),
sourceSignal2: this.sourceSignal2(),
}),
computation: (params: TypedLinkedSignal) => {
return params.sourceSignal * params.sourceSignal2 * 5;
},
});
}
bootstrapApplication(App);
The above explanation stays the same, only difference is we use a different data structure - array
.
So the way we access these properties is different.
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { model, linkedSignal } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-root',
imports: [FormsModule],
template: `
<input [(ngModel)]="sourceSignal"/>
<input [(ngModel)]="sourceSignal2"/>
<input [ngModel]="updatedSignal()"/>
`,
})
export class App {
sourceSignal = model(0);
sourceSignal2 = model(0);
updatedSignal = linkedSignal<Array<number>, number>({
source: () => [this.sourceSignal(), this.sourceSignal2()],
computation: ([sourceSignal, sourceSignal2]: Array<number>) => {
return sourceSignal * sourceSignal2 * 5;
},
});
}
bootstrapApplication(App);
The advantage of linked signal is that we can change the value using the set
or update
method, in contrast to computed
which was read only.
When the source signals change. The value changed via set
or update
is reset.