With Angular 16, we can now use Signals.
But it doesn't seem clear to me how to do a simple push into an array.
The documentation suggests from Angular Signal official doc:
When working with signals that contain objects, it's sometimes useful to mutate that object directly. For example, if the object is an array, you may want to push a new value without replacing the array entirely. To make an internal change like this, use the .mutate method
So it would be for example:
messages = signal<Message[]>([]);
ngOnInit(): void {
const newMessage = ...
this.messages.mutate(values => values.push(newMessage));
}
But it seems pretty weird to refer 2 times to the list. The first time with this.messages
and the second one with values
.
How can I push an item into a Signal array?
You should be using update
(instead of mutate that has been remove in v17).
Signal expect to be immutable (if you don't provide a compareFn when creating them).
messages = signal<Message[]>([]);
ngOnInit(): void {
const newMessage = ...
this.messages.update(values => {
return [...values, newMessage];
});
}
To sum up the types we are working with here:
Signal<Message[]>
Message[]
When you call update()
you're invoking the method on a Signal
. The signal here is the reactive primitive not the value itself.
You call that value with : messages()
. This is signals 101.
Cf the definition of signals by Angular:
const SIGNAL = Symbol('SIGNAL');
export type Signal<T> = (() => T)&{
[SIGNAL]: unknown;
};
So when you call update, you're actually telling the Signal to update its value.
Signal.set()
just accepts a value to set so you're changing the reference, while Signal.update()
takes a callback to update and you should be returning a new reference.