Gérer le CRUD sur une liste de données avec Angular ? Voici l’outil que me manquait[FR]

C’est l’outil que j’aurai aimé avoir pour ne plus perdre de temps à gérer les actions sur une liste de données avec Angular.

Le but est de pouvoir appliqué facilement des actions CRUD sur une entité de la liste ou sur les entités sélectionnés et de …


This content originally appeared on DEV Community and was authored by Romain Geffrault

Exemple of DataListStore

C'est l'outil que j'aurai aimé avoir pour ne plus perdre de temps à gérer les actions sur une liste de données avec Angular.

Le but est de pouvoir appliqué facilement des actions CRUD sur une entité de la liste ou sur les entités sélectionnés et de tracker les états de chargement.

Bien que ce soit encore un prototype et qu'il faut maintenant que je teste sur le terrain, la solution est:

-✅ Entièrement fonctionnelle
-⚡ 100% déclarative & réactive
-🧠 Type-safe (indispensable pour l'auto-complétion), tous les types sont inférés
-🚀 Performante & optimisée (compatible zoneless)
-🛠️ Facile à prendre en main et super rapide à mettre en place
-🎛️ Personnalisable, qui s'adapte aux cas les plus simples et complexes
-🌀 Bénéficie de la puissance de RxJs
-📭 Pas de boilerplate
-🧼 Pas de memoryleak

Elle permet:
-📊 de connaître l'état de chargement de la liste de données (loading, loaded, error...)
-✍️ d'appliquer une/des actions CRUD et de tracker l'état de chargement de chacune de ces actions sur chaque entité
-🤹‍♂️ d'appliquer en parallèle les actions sur chaque entité
-🧩 de sélectionner et d'appliquer une action sur l'ensemble des entités sélectionnées, tout en trackant au niveau de chaque entité l'état de chargement
-🧮 d'ajouter des sélecteurs (états dérivés) au niveau de chaque entité et de la liste globale
-🔄 de choisir la stratégie de requête à appliquer pour chaque action (switchMap, exhaustMap, concatMap, mergeMap)
-🧘 préserve l'affichage en cours lors du changement de page

Quand je dis action, cela peut-être un appel API (ex: mettre à jour le nom d'une entité via un appel API UPDATE ou PUT).

Comme tu vas le voir par la suite, je trouve que la porte d'entré pour utilisé cet outil est assez accessible et ne nécessite que quelque connaissances basic en RxJs, au minimum connaître les Subjects.

Si tu n'as pas l'habitude des Subjects, prends 2min pour regarder ce qu'ils font. Ils suffisent pour faire tourner l'outil.

Bref, j'ai créé un outil de server state management. Je l'ai nommé DataListStore et j'en suis très fière.

Voici comment il s'utilise et je serai curieux d'avoir ton avis dessus.

Définir des sources (RxJs), pagination et actions

Image description

Ces sources vont servir pour trigger les actions/appels API que l'on va définir.

Grâce à RxJs, ces sources ne nécessitent que d'être des observables et peuvent donc provenir de "stream" existants (état dérivé).

Si tu n'as pas l'habitude avec ce concept, ne t'embête pas avec ça maintenant, les Subject suffiront.

Comment utiliser DataListStore pour afficher une liste de données

Image description

Il suffit d'injecter DataListStore comme un service habituel en Angular.
Le store renvoie une fonction, qui attend en paramètre la config du store.
Les paramètres étant entièrement typé, cela est très facile à utiliser grâce à l'auto-complétion.

Pour simplement afficher une liste de données et de connaître son état de chargement (loading, loaded, error), il suffit de lui donner l'appel api pour récupéré la liste de données, ainsi que la source (généralement, c'est la pagination).

Image description

Dès la que la source émet une nouvelle valeur, cela va appeler l'api.

A noter qu'il faut aussi ajouter une fonction entityIdSelector qui permet de savoir comment identifier une entité. Je ne sais pas encore si je vais la garder.

Comment ajouter des actions CRUD et suivre leur état

Add DataListStore entityLevelAction

Ici j'ai ajouté une action (update) qui va s'appliquer au niveau d'une entité.

Il m'a suffit de lier la source de l'action avec l'appel API à effectuer.

Ces actions peuvent être appliquées en parallèle sur différentes entités.

Suivi des états de chargement pour chaque entité

Côté template, il est très facile d'afficher l'état de chargement (loaded, loading, error) pour chaque action appliqué à l'entité.

Pas besoin de se prendre la tête non plus lorsque l'on a besoin d'ajouter plusieurs actions (update, edit, create, put, quoi d'autre update2? ).

Multiples actions applicables sur chaque entité

Comment ajouter des actions de masse qui s'appliquent sur les entités sélectionnées

Comme pour les actions précédentes il suffit de lié une source qui émets une liste d'entités à un appel API et le tour est joué.

Ajouté des actions de masse pour géré une liste de données

Ici j'ajoute une action qui me permet de supprimer toutes les entités sélectionnées.

Supprimées plusieurs entités en même temps

On peut voir l'état de chargement au niveau de chaque entité sélectionné.

Simple et efficace non ?

Ajouter des sélecteurs (états dérivées)

J'ai l'impression de me répéter, mais grâce à l'auto-compéltion/typesafety, c'est très simple de les ajouter.

On peut ajouter des sélecteurs au niveau d'une entité mais aussi au niveau de store.

Ce sont des états dérivés qui sont calculés à chaque fois que le store émet une nouvelle valeur.

Image description

Je vais sans doute améliorer cette partie là encore, en permettant de récupérer les sélecteurs des niveau des entités, au sélecteurs du store.

Aller plus loin dans la personnalisation avec les reducer personnalisés

Déjà jusque là, je trouve l'outil déjà très cool. Mais je ne me suis pas arrêté là.

Ca peut-être utile de modifier une propriété de l'entité, que ce soit au chargement d'une action, à la fin de l'action suite à une succès ou une erreur.

Pour cela il est possible d'utiliser des reducers personnalisées pour chaque action.

Dans l'exemple qui suit, lors d'une création d'une entité, soit je l'ajoute à la liste si on est sur la première page soit, je la laisse dans la liste des outOfContextEntities.

Sans rentrer trop dans les détails, cette liste permet de tracker les entités qui ont eu des actions appliquées. Je ne sais pas encore si je vais la garder ou l'exposer.

Ajouter des reducer personnalisées

Aller toujours plus loin avec les delayedReducer

Inspiré par ce que propose l'opérateur groupBy de RxJs (duration), j'ai ajouté des reducer qui s'appliqueront "en décalé", toujours trigger par une source.

Dans l'exemple qui suit, j'ai ajouté une action bulkdDelete quand les entités sont supprimées, elle restent affichées avec l'état "Bulk deleted".

J'ai jouté un delayedReducer pour les enlever de la liste après 15s.

J'ai aussi ajouté un reducer pour ajouter une proprité ui.disappearIn$ à mon entité qui est un observable qui émet une string. Il va servir à afficher la phrase Remaining time before disappear: Xs et se mettre à jour chaque seconde.

C'est poussé par les cheveux ? Oui sans doute, mais ça m'amusait de pouvoir faire ça simplement.

Personnalisé l'ui au maximum avec les delayedreducer

Code à ajouter pour des reducers personnalisées

A noter que si l'utilisateur change de page, elles entités supprimées sont retirées.

La fonction remainingTimeBeforeDisappear

Voilà, je pense avoir fait le tour de ce que j'ai pu mettre en place.

Comme je l'ai dit, il faut maintenant tester ce système sur le terrain pour l'ajuster au mieux.

Le code final del'exemple

Code final du store

Quelques points d'améliorations

  1. Le nommage, je vais pour me rapprocher du nommage utilisé par TanStackQuery, pour plus d'harmonie.

  2. J'ai rencontré beaucoup de limitations TS en terme de typage et de contraintes de typage. J'ai trouvé une solution proche de ce que je souhaitais, mais qui a quelques limitations agaçantes.
    Bien que je n'ai pas eu besoin de déclarer de type à mon store, cela limite la façon dont je peux le moduler.

Je vais sans doute ajouter des fonctions intermédiaires avec des types parameters explicites pour améliorer la DX et certains cas de type-safety.

D'ailleurs, je vais essayer de faire un retour d'expérience avec les limitations de TS que j'ai rencontré lors du typage de ma fonction et les potentielles solutions.

  1. La pagination (la source qui trigger l'appel api des entités) est très basique ici, je pense qu'elle n'est pas tout à fait fiable et mérite d'évoluer pour s'adapter au mieux.

  2. Ajouter des events pour réagir plus facilement aux modifications de ce store.

  3. Clean le code de l'outil, je pensais partir sur un petit fichier pour géré le store, mais avec les imports et les types, je suis autour des 1000 lignes de code. C'est pas fou niveau lisibilité. Mais le code en lui même reste assez simple à suivre.

  4. Ajouter des fonctionnalités. Une fois sur le terrain, je verrai ce qui pourrait me simplifier encore la vie et ajouter de nouvelles fonctionnalités.

  5. Son principale défaut, c'est que le code peut faire un peu grand si on ajoute plusieurs actions et reducer. L'ajout de fonction intermédiaire peut régler ce problème.

Conclusion

Si cet outil de server state management t'intéresse, fais le moi savoir en commentaire, ou en mettant un like sur ce poste.

Je partagerai très prochainement le code, une fois que je l'aurai organiser.

Je ne pense pas faire de lib public pour le moment, car il faut encore que l'outil murisse et fasse ses première preuves. Et j'aurais sans doute besoin d'aide pour le maintenir.

En tout cas, je suis déjà très fière du résultat et je sais qu'il me fera déjà gagner beaucoup de temps.


This content originally appeared on DEV Community and was authored by Romain Geffrault


Print Share Comment Cite Upload Translate Updates
APA

Romain Geffrault | Sciencx (2025-04-02T17:59:29+00:00) Gérer le CRUD sur une liste de données avec Angular ? Voici l’outil que me manquait[FR]. Retrieved from https://www.scien.cx/2025/04/02/gerer-le-crud-sur-une-liste-de-donnees-avec-angular-voici-loutil-que-me-manquaitfr/

MLA
" » Gérer le CRUD sur une liste de données avec Angular ? Voici l’outil que me manquait[FR]." Romain Geffrault | Sciencx - Wednesday April 2, 2025, https://www.scien.cx/2025/04/02/gerer-le-crud-sur-une-liste-de-donnees-avec-angular-voici-loutil-que-me-manquaitfr/
HARVARD
Romain Geffrault | Sciencx Wednesday April 2, 2025 » Gérer le CRUD sur une liste de données avec Angular ? Voici l’outil que me manquait[FR]., viewed ,<https://www.scien.cx/2025/04/02/gerer-le-crud-sur-une-liste-de-donnees-avec-angular-voici-loutil-que-me-manquaitfr/>
VANCOUVER
Romain Geffrault | Sciencx - » Gérer le CRUD sur une liste de données avec Angular ? Voici l’outil que me manquait[FR]. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/04/02/gerer-le-crud-sur-une-liste-de-donnees-avec-angular-voici-loutil-que-me-manquaitfr/
CHICAGO
" » Gérer le CRUD sur une liste de données avec Angular ? Voici l’outil que me manquait[FR]." Romain Geffrault | Sciencx - Accessed . https://www.scien.cx/2025/04/02/gerer-le-crud-sur-une-liste-de-donnees-avec-angular-voici-loutil-que-me-manquaitfr/
IEEE
" » Gérer le CRUD sur une liste de données avec Angular ? Voici l’outil que me manquait[FR]." Romain Geffrault | Sciencx [Online]. Available: https://www.scien.cx/2025/04/02/gerer-le-crud-sur-une-liste-de-donnees-avec-angular-voici-loutil-que-me-manquaitfr/. [Accessed: ]
rf:citation
» Gérer le CRUD sur une liste de données avec Angular ? Voici l’outil que me manquait[FR] | Romain Geffrault | Sciencx | https://www.scien.cx/2025/04/02/gerer-le-crud-sur-une-liste-de-donnees-avec-angular-voici-loutil-que-me-manquaitfr/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.