3

Context:

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.

Question:

How can I push an item into a Signal array?

JSON Derulo
  • 9,780
  • 7
  • 39
  • 56
Wandrille
  • 6,267
  • 3
  • 20
  • 43
  • You are creating a signal and not an array with messages = signal([]); and in the next line you are using mutate to mutate the signal by modifying the existing value i.e. values.push(newMessage). If you want yo see the value of your signal then you can use this.messages(). Another way is to use update this.messages.update(()=> [...this.messages(), newMessage]); – Rohit Kawade May 07 '23 at 15:13

1 Answers1

6

Your code is absolutely correct:

messages = signal<Message[]>([]);

ngOnInit(): void {
   const newMessage = ...
   this.messages.mutate(values => values.push(newMessage));
}

To sum up the types we are working with here:

  • message: Signal<Message[]>
  • values: Message[]

When you call mutate() 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 mutate, 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.mutate() takes a callback to mutate the value and keep the reference.

Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134