Liens utiles :
Tout d'abord, forkez et clonez ce dépot.
En vous plaçant au sein du dossier, générez une nouvelle application avec Vite
:
npm create vite@latest
Pour le nom du projet, utilisez le caractère point (.
) pour que l'application soit générée dans le dossier courant.
Vite vous propose de supprimer les fichiers actuellement présents, acceptez.
Choisissez Svelte en tant que framework et TypeScript en tant que variante.
Installez les dépendances :
npm install
Enfin, lancez l'application :
npm run dev
L'application par défaut est accessible dans votre navigateur :
Pour faciliter le développement, installez l'extension Svelte for VSCode.
Afin de démarrer d'un environnement vierge :
App.svelte
, supprimer le contenu des balises <script>
, <main>
et <style>
app.css
Note : vous pouvez supprimer les autres fichiers inutiles si vous le souhaitez (Counter.svelte
, ...), mais il peut-être intéressant de les conserver pour s'en inspirer au cours du TP.
Commitez votre travail à la fin de chaque étape.
Nous travaillerons dans un premier temps dans le fichier App.svelte
.
Voici un exemple d'interface en TypeScript représentant un film :
interface Movie {
id: number;
title: string;
year: number;
running_time: number;
released: boolean;
}
Dans la partie <script>
, créez une interface Task
représentant une tâche à effectuer. Une tâche contient trois informations :
Créez une variable tasks
contenant un tableau de Task
. Utilisez TypeScript pour typer la variable. Voici par exemple un tableau de films :
const movies: Movie[] = [
{
id: 1,
title: 'Interstellar',
year: 2014,
running_time: 154,
released: true,
},
{
id: 2,
title: 'Blade Runner',
year: 1982,
running_time: 121,
released: true,
},
];
Ajoutez deux ou trois tâches à votre tableau. Vérifiez que le typage fonctionne : si vous ne le respectez pas, votre éditeur doit vous en informer.
Utilisez une boucle each pour afficher chaque le nom de chaque tâche dans une liste au sein de la balise <main>
.
Voici le résultat (que vous pouvez styliser selon vos envies) :
TodoList
Une application est généralement structurée en composants : on ne va pas tout stocker dans un fichier unique. On va même essayer de le remplir au minimum.
Notre première action va donc être de déplacer notre todo list dans un composant dédié.
Créez un fichier lib/TodoList.svelte
. Il sera structurée comme le composant App.svelte
: une balise <script>
, du HTML, puis une balise <style>
.
Déplacez le contenu des balises du fichier App.svelte
vers les balises du fichier TodoList.svelte
.
Dans la balise <script>
de App.svelte
, vous aller maintenant importer votre nouveau composant :
import TodoList from "./lib/TodoList.svelte";
Puis vous allez pouvoir l'utiliser :
<main>
<TodoList />
</main>
Le résultat est le même, mais notre application est un peu plus modulaire.
Devant le nom de chaque tâche, affichez une checkbox qui doit être cochée si la tâche est marquée comme réalisée. Vous devez pour cela lier l'état de la checkbox à la valeur associée à la tâche dans votre tableau de tâches.
Utilisez HTML pour lier la checkbox et le nom de la tâche grâce à la balise label : quand vous cliquez sur le nom de la tâche, la checkbox doit être ciblée.
Grâce à CSS :
Voici le résultat attendu à ce stade :
Créez une nouvelle variable dans votre composant : tasksLeftCount
, qui contiendra le nombre de tâches restantes.
let tasksLeftCount = ???
Vous pouvez compter les tâches restantes grâce à la fonction filter. En effet, il faut filtrer les tâches en fonction de leur statut, puis les compter. Utilisez console.log
pour vérifier que votre opération fonctionne bien.
Puis affichez le résultat sous la liste :
{tasksLeftCount} tâche(s) restante(s)
En l'état, vous devriez observer que le nombre affiché est correct au départ, mais ne se met pas à jour quand vous cochez de nouvelles tâches.
En effet, il faut avertir Svelte que cette propriété est réactive. Pour cela, utilisez le caractère spécial $
:
$: taskLeftCount = ???
L'interface doit maintenant réagir.
Enfin, si toutes les tâches sont complétées, affichez "Félicitation, c'est terminé !" à la place du décompte. Vous pouvez pour cela utiliser le if/else de Svelte.
Voici le résultat attendu :
Nous allons ajouter un bouton permettant de compléter toutes les tâches d'un seul coup :
Svelte permet d'appeler une fonction en réponse à un événement :
<button on:click={doSomething}>
Créez une fonction permettant de valider toutes les tâches, puis appelez-là au clic sur le bouton.
Lorsqu'il n'y a pas de tâche à compléter, le bouton doit être désactivé :
Le but de cette étape est d'ajouter un champ permettant d'ajouter une nouvelle tâche :
Pour cela, créez un composant NewTask
que vous inclurez au dessus de la liste.
Ce composant doit contenir un formulaire composé d'un unique champ requis, de son label correctement associé et d'un bouton de soumission.
Lorsque le formulaire est soumis, émettez un événement. Le composant parent doit récupérer l'événement et ajouter la tâche à la liste.
Note : la soumission d'un formulaire déclenche par défaut le rechargement de la page. Pour empêchez cela, vous devrez utiliser le modificateur d'événement approprié.
Pour les attributs de la nouvelle tâche, utilisez :
Date.now()
Vérifiez également que :
La définition de la liste des tâches n'a pas vraiment sa place dans le fichier TodoList.svelte
: actuellement, notre implémentation mélange données et présentation.
Pour remédier à cela, nous allons utiliser un store.
Créez un fichier lib/stores.ts
. Ajoutez y un writable
contenant la liste des tâches.
Dans TodoList.svelte
, remplacez la définition des tâches par un appel au store créé, en vous inspirant de la documentation.
Remplacez également le code de modification des données (ajout d'une tâche, validation des tâches...) par un appel à la méthode set
du store (voir documentation).
Le compteur de tâches restantes, quant à lui, peut être remplacé par un état dérivé avec la fonction derived
. De nouveau, inspirez-vous de la documentation pour remplacer le code nécessaire.
En plus de la sépatation entre données et présentation, l'utilisation d'un store a un gros avantage : plusieurs composants peuvent s'adresser au même store sans passer par un système d'événement.
Ainsi, vous allez pouvoir supprimer le code qui permettait de faire remonter l'événement de création d'une nouvelle tâche dans NewTask.svelte
.
À la place, l'ajout peut être effectué directement dans NewTask.svelte
. Sans communiquer entre eux, les deux composants interagissent avec le même store, et les changements sont répercutés dans l'ensemble des composants y faisant référence.
De nombreuses améliorations sont possibles :
localStorage
...