first comit
This commit is contained in:
149
README.md
Normal file
149
README.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# Démonstration 1 : Todo List (Hello, Signals!) - Gestion d'une Todo-List locale
|
||||
|
||||
Bienvenue dans cette première démonstration pratique d'Angular !
|
||||
L'objectif est de construire une application de type "Todo List" simple et entièrement fonctionnelle.
|
||||
Toutes les données et la logique seront contenues dans un seul composant,
|
||||
ce qui nous permettra de nous concentrer sur les concepts fondamentaux d'Angular moderne.
|
||||
|
||||
---
|
||||
|
||||
### Objectifs Pédagogiques
|
||||
|
||||
À la fin de cette démonstration, vous saurez :
|
||||
|
||||
* **Créer un état réactif** avec `signal()` pour stocker les données de votre application.
|
||||
* **Dériver un état** à partir d'un autre avec `computed()` pour des calculs automatiques.
|
||||
* **Gérer les entrées utilisateur** de manière robuste avec `FormControl`.
|
||||
* **Mettre à jour l'état** de manière immuable en utilisant la méthode `.update()` des signaux.
|
||||
* **Afficher dynamiquement des données** dans un template en utilisant la nouvelle syntaxe `@if` et `@for`.
|
||||
* **Lier des événements** du template (comme un clic) à des méthodes dans votre composant.
|
||||
|
||||
Voici un aperçu de la circulation des données que vous allez construire :
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
subgraph "État (Signals)"
|
||||
A["todos = signal<Todo[]>"]
|
||||
B[remainingTodos = computed]
|
||||
end
|
||||
|
||||
subgraph "Formulaire"
|
||||
C[newTodoTitle = FormControl]
|
||||
end
|
||||
|
||||
subgraph "Actions (Méthodes)"
|
||||
E[addTodo]
|
||||
F[removeTodo]
|
||||
G[toggleTodo]
|
||||
end
|
||||
|
||||
subgraph "Vue (Template HTML)"
|
||||
D[Affichage & Événements]
|
||||
end
|
||||
|
||||
%% Dépendances de données
|
||||
A -- "dérive de" --> B
|
||||
A -- "lu par" --> D
|
||||
B -- "lu par" --> D
|
||||
C -- "lu par" --> D
|
||||
|
||||
%% Flux d'actions
|
||||
D -- "clic / keydown" --> E
|
||||
D -- "clic" --> F
|
||||
D -- "clic" --> G
|
||||
D -- "saisie" --> C
|
||||
|
||||
E -- "appelle todos.update()" --> A
|
||||
F -- "appelle todos.update()" --> A
|
||||
G -- "appelle todos.update()" --> A
|
||||
E -- "appelle .reset()" --> C
|
||||
```
|
||||
|
||||
-----
|
||||
|
||||
### 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/`.
|
||||
|
||||
---
|
||||
|
||||
### Instructions
|
||||
|
||||
Le projet est volontairement déjà configuré.
|
||||
|
||||
Votre mission est de compléter le code dans les fichiers `todo-list.component.ts` et `todo-list.component.html` en suivant les indications `// TODO`.
|
||||
|
||||
Vous travaillerez sur deux fichiers qui interagissent comme suit :
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "Logique (Étape 1)"
|
||||
TS[todo-list.component.ts]
|
||||
end
|
||||
subgraph "Vue (Étape 2)"
|
||||
HTML[todo-list.component.html]
|
||||
end
|
||||
|
||||
TS -- "expose les données (signals, formControl)" --> HTML
|
||||
HTML -- "déclenche les méthodes (click), (keydown.enter)" --> TS
|
||||
```
|
||||
|
||||
#### Étape 1 : la logique du composant (`todo-list.component.ts`)
|
||||
|
||||
Ouvrez le fichier `app/features/todo/todo-list/todo-list.component.ts`.
|
||||
Nous allons d'abord définir l'état et les actions de notre composant.
|
||||
|
||||
1. **`// TODO 1.1` : Créer le signal d'état principal.**
|
||||
* Déclarez une propriété `readonly todos` et initialisez-la avec `signal<Todo[]>([...])`.
|
||||
* Utilisez le tableau de tâches fourni dans les commentaires pour avoir des données de départ.
|
||||
|
||||
2. **`// TODO 1.2` : Créer un signal dérivé (computed).**
|
||||
* Déclarez une propriété `readonly remainingTodos` et utilisez la fonction `computed()` pour calculer automatiquement le nombre de tâches non complétées à partir du signal `todos`.
|
||||
|
||||
3. **`// TODO 1.3` : Créer le contrôle de formulaire.**
|
||||
* Déclarez une propriété `readonly newTodoTitle` et initialisez-la avec un `new FormControl()`.
|
||||
* Assurez-vous qu'il ne peut pas être nul (`nonNullable: true`) et ajoutez des validateurs pour qu'il soit requis (`Validators.required`) et ait une longueur minimale (`Validators.minLength(3)`).
|
||||
|
||||
4. **`// TODO 1.4` : Implémenter la méthode `addTodo()`.**
|
||||
* À l'intérieur de la méthode, vérifiez d'abord si `newTodoTitle` est valide.
|
||||
* Créez un nouvel objet `Todo`.
|
||||
* Utilisez `this.todos.update(...)` pour ajouter la nouvelle tâche à la liste existante.
|
||||
* Réinitialisez le champ de saisie avec `.reset()`.
|
||||
|
||||
5. **`// TODO 1.5` : Implémenter la méthode `removeTodo()`.**
|
||||
* Utilisez `this.todos.update(...)` et la méthode `.filter()` des tableaux pour retourner une nouvelle liste sans la tâche à supprimer.
|
||||
|
||||
6. **`// TODO 1.6` : Implémenter la méthode `toggleTodo()`.**
|
||||
* Utilisez `this.todos.update(...)` et la méthode `.map()` des tableaux pour créer une nouvelle liste où l'état `completed` de la tâche ciblée est inversé.
|
||||
|
||||
#### Étape 2 : l'affichage et les interactions (`todo-list.component.html`)
|
||||
|
||||
Ouvrez le fichier `app/features/todo/todo-list/todo-list.component.html`.
|
||||
Maintenant que la logique est prête, connectons-la à notre vue.
|
||||
|
||||
1. **`// TODO 2.1` : Connecter le champ de saisie.**
|
||||
* Liez l'input au `FormControl` que vous avez créé en utilisant la liaison de propriété `[formControl]`.
|
||||
* Ajoutez un événement `(keydown.enter)` pour appeler la méthode `addTodo()` lorsque l'utilisateur appuie sur "Entrée".
|
||||
|
||||
2. **`// TODO 2.2` : Connecter le bouton "Ajouter".**
|
||||
* Liez l'événement `(click)` du bouton à la méthode `addTodo()`.
|
||||
* Désactivez le bouton si le formulaire est invalide en utilisant `[disabled]`.
|
||||
|
||||
3. **`// TODO 2.3` : Afficher la liste des tâches.**
|
||||
* Utilisez un bloc `@if` pour vérifier si la liste `todos()` contient des éléments.
|
||||
* À l'intérieur, utilisez une boucle `@for` pour itérer sur `todos()`. N'oubliez pas le `track todo.id` pour les performances !
|
||||
* Affichez le titre de la tâche en utilisant l'interpolation `{{ ... }}`.
|
||||
* Appliquez la classe `.completed` dynamiquement avec `[class.completed]`.
|
||||
|
||||
4. **`// TODO 2.4` : Ajouter les actions sur chaque tâche.**
|
||||
* Dans la boucle `@for`, liez l'événement `(click)` du `<span>` à la méthode `toggleTodo(todo.id)`.
|
||||
* Liez l'événement `(click)` du bouton de suppression à la méthode `removeTodo(todo.id)`.
|
||||
|
||||
5. **`// TODO 2.5` : Afficher le compteur de tâches restantes.**
|
||||
* Dans le `<footer>`, affichez la valeur du signal `remainingTodos()` en utilisant l'interpolation. N'oubliez pas les parenthèses `()` pour lire la valeur d'un signal !
|
||||
|
||||
Une fois toutes les étapes terminées, votre application devrait être entièrement fonctionnelle !
|
||||
Reference in New Issue
Block a user