Et oui, Angular change, et change vers une version plus souple, moins Zone.js (bientĂŽt la fin). AprĂšs l’arrivĂ©e de la Standalone API, ce bien fou dans la strcuturation et l’appel de nos composants, nous passons maintenant Ă une nouvelle Ă©tape : l’utilisation des Signals, pour dĂ©cider quand on update vraiment la Vue, son template. Fini l’auto update, de Zone.js.
DĂ©couvrons ensemble la mise en place des Signals, dans un composant, vers l’utilisation avec ngRx.
Mise en place du signal dans un composant
Un Signal est une fonction, qui gÚre un état pour un composant, ou un service.
Cet Ă©tat va ĂȘtre garder en mĂ©moire, jusqu’Ă la prochaine demande de changement.
Oui, vous avez bien lu ! Nous allons faire la demande de changement. Ce n’est plus zone.js qui va interprĂ©ter le binding de notre champ, en dĂ©tectant si sa valeur / rĂ©fĂ©rence change. C’est nous qui dĂ©cidons le changement.
Si vous avez dĂ©jĂ fait du React, ça ressemble Ă©trangement Ă un useState. Chut, on ne dira rien de plus …
CrĂ©ation d’un Signal pour mettre Ă jour notre titre
title = signal<string>('Mes films');
En regardant le type retourné, nous avons un signal, qui est modifiable. Car oui, nous pouvons aussi avoir des signaux en lecture seule, calculés.
Appeler notre signal sur la vue
Notre signal est une fonction. Donc, bien qu’Ă©trange, nous allons exĂ©cuter notre fonction pour rĂ©cupĂ©rer la derniĂšre valeur mĂ©moisĂ©e. En mĂȘme temps, nous venons de nous abonner au Signal, en tant qu’observer.
C’est vraiment dĂ©routant, sachant que j’ai pu le rĂ©pĂ©ter de nombreuses fois : normalement il faut Ă©viter d’appeler des fonctions du cĂŽtĂ© template (du fait de la non mĂ©moization, de l’exĂ©cution multiple Ă cause de Zone.js)
Voyons voir ce que ça donne :
{{ title() }}
Si nous appelons le signal comme un champ, nous récupérons un warning à bien écouter :

(pour bien comprendre les signaux,je vous invite Ă aller voir aussi cet article qui regarde comment fonctionne en interne un Signal)
Les computed
Avec notre Signal, mutable, nous pouvons construire, tout comme les selectors dans NgRx, des computable signal, qui sont en lecture seul.
isEmptyList = computed(() => {
return this.listItems().length === 0;
})
Utilisable ainsi
@if(isEmptyList())
{
<i>Aucun élément dans la liste</i>
}
Notons que le computed s’exĂ©cute toujours aprĂšs les signaux parents.
Ngrx et les signaux
Ngrx propose une refonte de son store : signalStore.
Ce store peut ĂȘtre soit créé par composant, soit global, en singleton pour toute l’application. Cela change de l’approche ngrx classique (action, effect, selector, reducer).
Préparation du SignalStore
export const BooksStore = signalStore(
{ providedIn: 'root' },
withState(initialBookState),
withMethods((store, bookInfra = inject(GetAllBooksInfrastructure)) => ({
loadAll: rxMethod<string>(
pipe(
tap(() => patchState(store, { isLoading: true })),
switchMap(filter => bookInfra.getAll({ value: filter }).pipe(
tapResponse({
next: items => patchState(store, { items }),
error: () => patchState(store, { isOnError: true }),
finalize: () => patchState(store, { isLoading: false })
})
)),
)
)
}))
Notons ici plusieurs points importants :
Le signalStore s’appuie sur un Ă©tat initial, qui va crĂ©er sa structure aussi au signal renvoyĂ©.
ici notre état est :
export interface BooksState {
items: Books;
isLoading: boolean;
isOnError ?: boolean;
}
export const initialBookState: BooksState = {
items: [],
isLoading: false
}
Puis nous appelons un chargement des données depuis un interop rxjs : rxMethode.
Nous mettons à jour une partie de notre état avec patchState.
Enfin, vous avez du noter le { providedIn: ‘root’ } qui permet de le prĂ©parer en singleton.
Utilisation de notre signalStore
private readonly booksStore = inject(BooksStore);
Nous allons pouvoir l’injecter et l’appeler par la suite dans le template. C’est un signal, donc appelons la fonction liĂ©e Ă notre structure de notre State.
CÎté component : books$$ = this.application.getAll();
CÎté template :
@for (book of books$$(); track book.id) {
<div>
{{book.title}}
</div>
}
Et voilĂ , le tour est jouĂ© avec un gestionnaire d’Ă©tat ngrx basĂ© sur des signaux !