+ }
diff --git a/src/app/features/todo/todo-list/todo-list.component.ts b/src/app/features/todo/todo-list/todo-list.component.ts
index 3aa6978..41b5b0b 100644
--- a/src/app/features/todo/todo-list/todo-list.component.ts
+++ b/src/app/features/todo/todo-list/todo-list.component.ts
@@ -7,61 +7,62 @@ import { Todo } from '../../../core/models/todo.model';
templateUrl: './todo-list.component.html',
styleUrls: ['./todo-list.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
- imports: [ReactiveFormsModule],
+ imports: [ReactiveFormsModule], // Importer ReactiveFormsModule pour utiliser FormControl
})
export class TodoListComponent {
// --- ÉTAT (State) ---
- // TODO 1.1: Créer un signal pour stocker la liste des tâches.
- // Utilisez `signal()` et initialisez-le avec le tableau ci-dessous.
- /*
- [
- { id: 1, title: 'Apprendre les bases d\'Angular', completed: true },
- { id: 2, title: 'Comprendre les signals', completed: false },
- { id: 3, title: 'Créer un premier composant', completed: false },
- ]
- */
- readonly todos = signal([]); // <- REMPLACER [] par le tableau ci-dessus
+ // Le signal `todos` est la source de vérité pour notre liste de tâches.
+ // On utilise `signal(valeurInitiale)` pour le créer.
+ readonly todos = signal([
+ { id: 1, title: 'Apprendre les bases d\'Angular', completed: true },
+ { id: 2, title: 'Comprendre les signals', completed: false },
+ { id: 3, title: 'Créer un premier composant', completed: false },
+ ]);
+ // Un signal `computed` dérive sa valeur d'autres signaux.
+ // Il se met à jour automatiquement quand `todos` change.
+ readonly remainingTodos = computed(() => this.todos().filter(t => !t.completed).length);
- // TODO 1.2: Créer un signal "computed" pour calculer le nombre de tâches restantes.
- // Utilisez `computed(() => ...)` et filtrez le signal `todos` pour ne compter
- // que les tâches où `completed` est `false`.
- readonly remainingTodos = computed(() => 0); // <- REMPLACER 0 par le calcul
-
-
- // TODO 1.3: Créer un FormControl pour le champ de saisie d'une nouvelle tâche.
- // Utilisez `new FormControl()` avec une chaîne vide comme valeur initiale.
- // Dans les options, ajoutez `nonNullable: true` et des validateurs :
- // `Validators.required` et `Validators.minLength(3)`.
- readonly newTodoTitle = new FormControl(''); // <- AJOUTER les options
-
+ // Utilisation d'un FormControl pour gérer l'input de manière réactive.
+ readonly newTodoTitle = new FormControl('', {
+ nonNullable: true,
+ validators: [Validators.required, Validators.minLength(3)],
+ });
// --- ACTIONS ---
/** Ajoute une nouvelle tâche à la liste. */
addTodo(): void {
- // TODO 1.4: Implémenter la logique d'ajout.
- // 1. Vérifiez si `this.newTodoTitle` est invalide. Si c'est le cas, arrêtez la fonction avec `return;`.
- // 2. Créez un objet `newTodo` de type `Todo` avec un `id` unique (Date.now()),
- // le titre provenant de `this.newTodoTitle.value`, et `completed: false`.
- // 3. Mettez à jour le signal `todos` avec `this.todos.update(currentTodos => [...currentTodos, newTodo])`.
- // 4. Réinitialisez le champ de saisie avec `this.newTodoTitle.reset()`.
+ if (this.newTodoTitle.invalid) {
+ return; // Ne rien faire si l'input est invalide
+ }
+
+ const newTodo: Todo = {
+ id: Date.now(), // Utilisation d'un timestamp pour un ID unique simple
+ title: this.newTodoTitle.value,
+ completed: false,
+ };
+
+ // `update` permet de modifier la valeur du signal en se basant sur la valeur actuelle.
+ // C'est une bonne pratique de créer un nouveau tableau (immuabilité).
+ this.todos.update(currentTodos => [...currentTodos, newTodo]);
+
+ this.newTodoTitle.reset(); // Vider le champ de saisie
}
/** Supprime une tâche de la liste. */
removeTodo(id: number): void {
- // TODO 1.5: Implémenter la logique de suppression.
- // Utilisez `this.todos.update(currentTodos => ...)` et la méthode `.filter()`
- // pour retourner un nouveau tableau sans la tâche correspondant à l'`id`.
+ this.todos.update(currentTodos => currentTodos.filter(todo => todo.id !== id));
}
/** Bascule l'état "complété" d'une tâche. */
toggleTodo(id: number): void {
- // TODO 1.6: Implémenter la logique de bascule.
- // Utilisez `this.todos.update(currentTodos => ...)` et la méthode `.map()`.
- // Pour chaque `todo` dans le tableau, si son `id` correspond, retournez un nouvel objet
- // avec la propriété `completed` inversée (`!todo.completed`). Sinon, retournez le `todo` original.
+ this.todos.update(currentTodos =>
+ currentTodos.map(todo =>
+ todo.id === id ? { ...todo, completed: !todo.completed } : todo
+ )
+ );
}
}