2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00
2025-12-17 09:53:44 +01:00

Démonstration 2 : Service, Observable, réactivité et formulaires

Nous allons maintenant faire évoluer notre application pour adopter une architecture plus robuste et professionnelle. L'objectif est de séparer la gestion des données de l'affichage en introduisant un service. Ce service agira comme une fausse API (une "API en mémoire"), gérant l'état de nos tâches.

Nous allons également créer un formulaire réactif pour ajouter de nouvelles tâches, ce qui nous permettra de voir comment la liste se met à jour en temps réel grâce à la puissance des signaux.

Architecture cible : service et réactivité

Ce diagramme montre comment les composants interagissent avec le service pour lire les données (flux de réactivité) et pour envoyer des actions (flux d'événement).

graph TD
    subgraph "Flux de Données (Réactivité)"
        direction TB
        S(TodoApiService) -- "gère" --> SP["signal privé todos"]
        SP -- "expose" --> SR["signal public todos$.asReadonly()"]
        TLC(TodoListComponent) -- "lit (s'abonne)" --> SR
        TLC -- "affiche les données" --> HTML[Template HTML]
    end

    subgraph "Flux d'Action (Événement)"
        direction LR
        User[Utilisateur] -- "clique" --> HTML
        HTML -- "appelle (click)='toggleTodo(id)'" --> TLC
        TLC -- "délègue l'action" --> S
        S -- "met à jour l'état" --> SP
    end

Objectifs pédagogiques

À la fin de cette démonstration, vous saurez :

  • Créer un service pour centraliser la logique et l'état des données.
  • Utiliser l'injection de dépendances avec inject() pour fournir le service aux composants.
  • Exposer un état réactif depuis un service en utilisant un signal public en lecture seule (.asReadonly()).
  • Créer un formulaire réactif complet avec FormBuilder et des validateurs.
  • Gérer la soumission d'un formulaire, appeler une méthode de service asynchrone (Observable) et gérer la navigation.
  • Construire une application entièrement réactive où les changements de données dans le service sont instantanément reflétés dans l'interface utilisateur.

Installation

  1. Ouvrir le projet sous WebStorm.
  2. Ouvrir un terminal dans WebStorm.
  3. Lancer la commande npm install pour installer les dépendances.
  4. Lancer la commande ng serve pour démarrer le serveur de développement.
  5. Ouvrir le navigateur à l'adresse http://localhost:4200/.

Flux de soumission du formulaire

L'étape 3 vous demandera de gérer la création d'une tâche. Voici le flux logique de la soumission du formulaire que vous allez implémenter.

graph TD
    A["Utilisateur clique Enregistrer"] --> B(TodoFormComponent.saveTodo)
    B -- "Vérifie" --> C{Formulaire valide ?}
    C -- "Non" --> D[Fin : Affiche erreurs de validation]
    C -- "Oui" --> E[Prépare le payload des données]
    E --> F(Appelle TodoApiService.createTodo)
    F -- "Retourne" --> G["Observable simule délai réseau"]
    B -- "Souscrit à l'Observable" --> G
    G -- "Émet la tâche créée (next)" --> H(Callback .subscribe)
    H -- "Appelle" --> I(Router.navigate vers la liste)
    I --> J[Fin : Redirection effectuée]

Instructions

Le projet est déjà configuré. Votre travail est de compléter le code dans les fichiers indiqués en suivant les // TODO.

Étape 1 : le cerveau de l'application - le service

Ouvrez le fichier app/core/services/todo.service.ts. C'est ici que nous allons centraliser toute la gestion de nos tâches.

  1. // TODO 1.1 : Créer la source de vérité.
  • Déclarez un signal privé nommé todos pour stocker le tableau de tâches.
  1. // TODO 1.2 : Exposer les données de manière sécurisée.
  • Déclarez une propriété publique todos$ qui expose le signal todos en lecture seule grâce à la méthode .asReadonly(). C'est ce que les composants utiliseront pour lire les données.
  1. // TODO 1.3 : Implémenter la création d'une tâche.
  • Dans la méthode createTodo, créez un nouvel objet Todo.
  • Utilisez this.todos.update() pour ajouter la nouvelle tâche à la liste.
  • Retournez la nouvelle tâche dans un Observable qui simule un délai réseau avec of(...).pipe(delay(...)).
  1. // TODO 1.4 : Implémenter les interactions.
  • Complétez les méthodes toggleTodo et deleteTodo pour qu'elles mettent à jour le signal privé todos en utilisant .map() (pour basculer) et .filter() (pour supprimer).

Étape 2 : connecter la liste au Service

Ouvrez le fichier app/features/todo/todo-list/todo-list.component.ts. Ce composant ne gérera plus les données lui-même, il va simplement les afficher et déléguer les actions au service.

  1. // TODO 2.1 : Injecter le service.
  • Utilisez inject(TodoApiService) pour obtenir une instance de votre service.
  1. // TODO 2.2 : Se connecter au flux de données.
  • Connectez le signal todos du composant directement au signal public todos$ de votre service.
  1. // TODO 2.3 : Déléguer les actions.
  • Dans les méthodes toggleTodo et deleteTodo du composant, appelez simplement les méthodes correspondantes de votre service.

Étape 3 : créer le formulaire d'ajout

Ouvrez le fichier app/features/todo/todo-form/todo-form.component.ts. Nous allons construire ici le formulaire de création.

  1. // TODO 3.1 : Injecter les outils nécessaires.
  • Injectez le FormBuilder, le Router et votre TodoApiService.
  1. // TODO 3.2 : Construire le formulaire.
  • Utilisez this.fb.nonNullable.group({...}) pour définir la structure de votre formulaire avec les champs title et completed et leurs validateurs.
  1. // TODO 3.3 : Gérer la soumission.
  • Dans la méthode saveTodo, vérifiez si le formulaire est valide.
  • Préparez le payload (les données à envoyer) à partir des valeurs du formulaire.
  • Appelez la méthode createTodo de votre service. Comme elle retourne un Observable, vous devez y souscrire avec .subscribe({...}).
  • Dans le next de la souscription, redirigez l'utilisateur vers la liste des tâches avec this.router.navigate(...).

Étape 4 : activer les interactions dans les templates

Il ne reste plus qu'à connecter les actions dans les fichiers HTML.

  1. // TODO 4.1 : Dans todo-list.component.html
  • Assurez-vous que les événements (click) sur le <span> et le bouton de suppression appellent bien les méthodes toggleTodo(todo.id) et deleteTodo(todo.id).
  1. // TODO 4.2 : Dans todo-form.component.html
  • Liez le formGroup à la balise <form>.
  • Liez l'événement (ngSubmit) à votre méthode saveTodo().
  • Connectez chaque input à son formControlName.

Une fois toutes les étapes terminées, votre application sera entièrement fonctionnelle... et réactive !

Description
No description provided
Readme 133 KiB
Languages
TypeScript 47.8%
SCSS 39.9%
HTML 12.3%