NGRX signals - Un gestionnaire d'état complet
Avec la montée en puissance des signaux, ngrx signal a pris de plus en plus d'importance. Les devs ont rapidement voulu intégrer ce gestionnaire d'état. A la différence de son grand frère : ngrx, il se voulait plus facile à mettre en place, moins verbeux, moins de fichiers. Mais, il manquait une fonctionnalité pour être vraiment utilisable. Les Events.
Les fondamentaux
Création du signal store
export const WeatherStore = signalStore(
{providedIn: 'root'},
withState(initDefaultState())
);
Le withState permet d'injecter l'état initial.
POINT important : chaque propriété du state est un signal à part.
Ici, noton le provided in root qui permet d'injecter le store de manière singleton dans tout l'application.
Tips : plutot qu'un singleton : on peut aussi l'injecter dans le providers de la route.
export const routes: Routes = [{path: 'afternoons',children: afternoonsRoutes,providers: [ AfternoonStore ]},
Travail sur les méthodes du store ngrx signal
Tu peux ajouter des méthodes dédiées qui communiquent avec le store.
withMethods(store => ({addOne(item: Afternoon) {patchState(store, ({ items: [...store.items(), item] }))},clear(): void {patchState(store, getDefaultListState());}})),
Ajout de computed dédiés
Tu peux ajouter des données calculés, qui travaillent avec des computed pour être connectés aux signaux du store.
withComputed(store => ({nbItems: computed(() => store.items().length),filteredItems: computed(() => store.items().filter(item => {const filter = store.filter();return item.status.includes(filter.query) || item.date.toDateString().includes(filter.query);}))})),
Ici, on ajoute deux propriétés au store, qui sont des signal en readonly.
Connexion à des linked signal
On peut également, et c'est vraiment une belle évolution : créer des linked signal (la fonctionnalité la moins bien connue de angular 21 selon moi ... beaucoup font des effects à la place ... ce qui est une erreur réelle d'implémentation)
withLinkedState(store => ({first: () => store.items()[0]})),
Le game changer de ngrx signal 21
Si tu as déjà utilisé ngrx tu sais qu'il y a un point essentiel, qui fait partie du coeur du système : les actions. Elles permettent de parler à N reducers et de déclencher la mise à jour de plusieurs états, sans créer de dépendance entre domain / bounded context / zone métier indépendante.
Il manquait vraiment cette fonctionnalité dans ngrx signal ! Plus d'actions, non, on parlera de "event".
Création d'un event : seul ou par groupe
Première étape : création des événements. On peut les créer indépendemment, ou bien par group.
Je te recommande par groupe : plus propre et plus lisible.
export const afternoonEvents = eventGroup({source: 'Afternoons search page',events: {loadedSuccess: type<Afternoon[]>(),loadedFailure: type<string>()}})
Création de nos reducers
Les reducers ont le rôle de mettre à jour l'état suivant l'abonnement sur un event.
withReducer(on(afternoonEvents.loadedSuccess, (event, state) => ({...state,items: event.payload,loading: false,})),on(afternoonEvents.loadedFailure, (event, state) => ({...state,error: event.payload,loading: false,}))),
Il nous reste plus qu'une étape, crucial : pouvoir appeler l'api et envoyé un event pour informer le reducer !
withEventHandlers
Avec withEventHandlers, on va pouvoir coupler l'abonnement sur un évément et l'enchainement d'operator rxjs. Ca permet de produire une observable !
withEventHandlers((store,events = inject(Events),getCurrentWeatherInfra = inject(GetCurrentWeatherInfra)) => ({loadWeather$: events.on(weatherEvents.get).pipe(tap(() => patchState(store, { loading: true })),switchMap(() => getCurrentWeatherInfra.getOne().pipe(mapResponse({next: weather => weatherEvents.loadedSuccess(weather),error: err => console.error(err)}))))})),
Et tu noteras qu'on peut appeler un service plutot que tout mettre dans le store !
Dispatching de l'event
Dernier point : pour déclencher un évenement, on va utiliser un service dédié : le Dispatcher.
private readonly dispatcher = inject(Dispatcher);ngOnInit(): void {this.dispatcher.dispatch(weatherEvents.get());}
withHooks({onInit(store) {setInterval(() => store.load(), 900);}})
withMethods((store, dispatcher = inject(Dispatcher)) => ({load(): void {dispatcher.dispatch(weatherEvents.get());}})),
Conclusion
Tu l'as vu, ngrx signal, avec l'apparition des events, est vraiment un game changer pour ton application angular 21.
Vu que tout est signal : tupeux travailler avec un form (experimental) !
Tout s'organise parfaitement !
Reste à se poser la question de comment intégrer les resource avec ce gestionnaire d'état ... nous en reparlerons plus tard !
Hey, tu sais qu'on donne des formations angular next gen ?
- ngrx signal : https://www.devtobecurious.fr/formations-developpeur/front-end/angular-19-etat-ngrx-signals
- angular next gen : https://www.devtobecurious.fr/formations-developpeur/front-end/formation-angular-17-19-signal-ready
- angular avancé : https://www.devtobecurious.fr/formations-developpeur/front-end/angular-19-avance