From 00b53558615aa7f297a8e78e46ddc6dc7fea325e Mon Sep 17 00:00:00 2001 From: Johan Date: Wed, 17 Dec 2025 09:50:36 +0100 Subject: [PATCH] TP done --- .../todo/todo-list/todo-list.component.html | 37 +++++----- .../todo/todo-list/todo-list.component.ts | 73 ++++++++++--------- 2 files changed, 57 insertions(+), 53 deletions(-) diff --git a/src/app/features/todo/todo-list/todo-list.component.html b/src/app/features/todo/todo-list/todo-list.component.html index 6baca98..e85d33e 100644 --- a/src/app/features/todo/todo-list/todo-list.component.html +++ b/src/app/features/todo/todo-list/todo-list.component.html @@ -5,25 +5,28 @@ - - + - - - - -

Bravo, aucune tâche pour le moment !

- + @if (todos().length > 0) { + + + } @else { +

Bravo, aucune tâche pour le moment !

+ } 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 + ) + ); } }