Bases de Svelte
Introduction
Liaisons
Classes et styles
Svelte avancé
Réutiliser du contenu
Mouvements
Liaisons avancées
Transitions avancées
API de contexte
Éléments spéciaux
<script module>
Next steps
Bases de SvelteKit
Introduction
Routing
Chargement de données
En-têtes et cookies
Modules partagés
Formulaires
$app/state
Erreurs et redirections
SvelteKit avancé
Options de page
Options de lien
Routing avancé
Chargement avancé
Variables d’environnement
Conclusion
Avec use:enhance
, nous pouvons aller plus loin que simplement nous contenter d’émuler le
comportement natif du navigateur. En fournissant un callback, nous pouvons ajouter des choses comme
des états d’attente et des interfaces optimistes. Simulons un réseau dégradé en ajoutant un
retard artificiel sur nos deux actions :
export const actions = {
create: async ({ cookies, request }) => {
await new Promise((fulfil) => setTimeout(fulfil, 1000));
...
},
delete: async ({ cookies, request }) => {
await new Promise((fulfil) => setTimeout(fulfil, 1000));
...
}
};
Lorsque nous créons ou supprimons des tâches, cela prend maintenant une seconde complète avant que l’interface ne se mette à jour, laissant l’utilisateur ou l’utilisatrice le temps de se demander si quelque chose ne va pas. Pour résoudre cela, ajoutons un état local...
<script>
import { fly, slide } from 'svelte/transition';
import { enhance } from '$app/forms';
let { data, form } = $props();
let creating = $state(false);
let deleting = $state([]);
</script>
<script lang="ts">
import { fly, slide } from 'svelte/transition';
import { enhance } from '$app/forms';
let { data, form } = $props();
let creating = $state(false);
let deleting = $state([]);
</script>
... et activons creating
dans le premier use:enhance
:
<form
method="POST"
action="?/create"
use:enhance={() => {
creating = true;
return async ({ update }) => {
await update();
creating = false;
};
}}
>
<label>
ajouter une tâche :
<input
disabled={creating}
name="description"
value={form?.description ?? ''}
autocomplete="off"
required
/>
</label>
</form>
Nous pouvons alors afficher un message pendant que les données sont enregistrées :
<ul class="todos">
<!-- ... -->
</ul>
{#if creating}
<span class="saving">sauvegarde en cours...</span>
{/if}
Pour ce qui est des suppressions, nous n’avons pas vraiment besoin d’attendre que le serveur valide quelque chose — nous pouvons juste mettre à jour l’interface immédiatement :
<ul class="todos">
{#each data.todos.filter((todo) => !deleting.includes(todo.id)) as todo (todo.id)}
<li in:fly={{ y: 20 }} out:slide>
<form
method="POST"
action="?/delete"
use:enhance={() => {
deleting = [...deleting, todo.id];
return async ({ update }) => {
await update();
deleting = deleting.filter((id) => id !== todo.id);
};
}}
>
<input type="hidden" name="id" value={todo.id} />
<button aria-label="Marquer comme fait">✔</button>
{todo.description}
</form>
</li>
{/each}
</ul>
use:enhance
est très personnalisable — vous pouvez annuler des soumissions aveccancel()
, gérer les redirections, contrôler la réinitialisation du formulaire, parmi d’autres. Voir la documentation pour plus de détails.
Modifier cette page sur Github
<script>
import { fly, slide } from 'svelte/transition';
import { enhance } from '$app/forms';
let { data, form } = $props();
</script>
<div class="centered">
<h1>à faire</h1>
{#if form?.error}
<p class="error">{form.error}</p>
{/if}
<form method="POST" action="?/create" use:enhance>
<label>
ajouter une tâche :
<input
name="description"
value={form?.description ?? ''}
autocomplete="off"
required
/>
</label>
</form>
<ul class="todos">
{#each data.todos as todo (todo.id)}
<li in:fly={{ y: 20 }} out:slide>
<form method="POST" action="?/delete" use:enhance>
<input type="hidden" name="id" value={todo.id} />
<span>{todo.description}</span>
<button aria-label="Marquer comme fait"></button>
</form>
</li>
{/each}
</ul>
</div>
<style>
.centered {
max-width: 20em;
margin: 0 auto;
}
label {
width: 100%;
}
input {
flex: 1;
}
span {
flex: 1;
}
button {
border: none;
background: url(./remove.svg) no-repeat 50% 50%;
background-size: 1rem 1rem;
cursor: pointer;
height: 100%;
aspect-ratio: 1;
opacity: 0.5;
transition: opacity 0.2s;
}
button:hover {
opacity: 1;
}
.saving {
opacity: 0.5;
}
</style>