Enhance π¦ Angular Signals π¦ with Super Powers!
npm i sygnalyze
π stackblitz.com/edit/sygnalyze
sygnal
is a tiny wrapper which improve Angularsignal
DX- that means that 100% runtime of Angular signals is preserved and are meant to be always compatible
- i.e.
computed
,effects
,toSignal
/toObservable
will work withsygnal
the same way as withsignal
Enhanced Angular Signal - with 2 differences:
The update
method parameter (current value) is DeepReadonly
in order to avoid unintentional mutations
import { sygnal } from 'sygnalyze';
const item = sygnal({
name: 'john',
age: 40
})
item.update(current => ...)
// ^? current is DeepReadonly
An additional method draftUpdate(mutatingCallback)
allows to mutate the current value of the signal, but thanks to using immer
, the value is replaced with an immutable
import { sygnal } from 'sygnalyze';
const item = sygnal({
name: 'john',
age: 40
})
item.draftUpdate(draft => {
draft.age++;
})
In above code, a new object is set as the value, so the signal notifies all its dependents.
Make a snapshot (memento) of the signal's value at a certain point in time. Whenever memento gets restored, the signal goes back to that value.
import { signal } from '@angular/core';
import { memento, withMemento, Memento } from 'sygnalyze'
export class TheComponent {
item = memento({ age: 40 }) // WritableSygnal
// or:
item = withMemento(signal({ age: 40 })) // original Signal
...
memento?: Memento
createMemento(){
this.memento = this.item.memento()
}
restoreMemento(){
this.memento?.restore()
}
}
Creates a boolean signal with simple toggle()
updating method.
import { signal } from '@angular/core';
import { toggle, withToggle } from 'sygnalyze'
export class TheComponent {
showTheThing = toggle(true) // Sygnal
// or:
showTheThing = withToggle(signal(true)) // original Signal
...
theMethod(){
this.showTheThing.toggle()
}
}
The NGRX Signal Store patchState
function enhanced with immer
immutability:
import { immutablePatchState } from 'sygnalyze/ngrx'
export const Store = signalStore(
withMethods((store) => ({
updateOrder(order: 'asc' | 'desc'): void {
immutablePatchState(store, (draft) => { draft.filter.order = order });
},
})
)
The immutablePatchState
function callback can now mutate the state draft object and return nothing. immer
will create a new object by applying all recorded changes. You don't have to worry about applying immutable changes manually.
Compare with default approach:
import { signalStore, withMethods, ... } from '@ngrx/signals'
import { immutablePatchState } from 'sygnalyze/ngrx'
export const Store = signalStore(
//...
withMethods((store) => ({
// state: WritableDraft<StateType>
updateOrderMutative(order: 'asc' | 'desc'): void {
immutablePatchState(store, (draft) => { draft.filter.order = order });
},
// BEFORE: having to apply immutability manually by spread operator:
updateOrder(order: 'asc' | 'desc'): void {
patchState(store, (state) => ({ filter: { ...state.filter, order } }));
},
})
)