Cours Svelte et SvelteKit · Module 4: Props et événements
Liaisons bidirectionnelles ($bindable)
Dans cette leçon4
Parfois, tu as besoin qu'un enfant puisse modifier les données du parent. Utilise $bindable !
$bindable en Svelte 5
<!-- SearchInput.svelte -->
<script>
let { value = $bindable('') } = $props();
</script>
<input bind:value placeholder="Chercher un guerrier..." /><!-- Parent.svelte -->
<script>
import SearchInput from './SearchInput.svelte';
let searchQuery = $state('');
</script>
<SearchInput bind:value={searchQuery} />
<p>Tu cherches : {searchQuery}</p>Quand utiliser $bindable ?
Bons cas d'usage :
- Champs de formulaire
- Composants contrôlés (select, slider)
- Modale avec contrôle de visibilité
À éviter quand :
- Un flux de données à sens unique suffit
- La logique de mise à jour est complexe
- Il y a plusieurs sources de vérité
Exemple : Slider
<!-- VolumeSlider.svelte -->
<script>
let { value = $bindable(50), min = 0, max = 100 } = $props();
</script>
<div class="slider">
<input
type="range"
bind:value
{min}
{max}
/>
<span>{value}</span>
</div>
<style>
.slider {
display: flex;
align-items: center;
gap: 1rem;
}
</style><!-- Parent.svelte -->
<script>
import VolumeSlider from './VolumeSlider.svelte';
let warHornVolume = $state(75);
</script>
<h3>Volume du cor de guerre</h3>
<VolumeSlider bind:value={warHornVolume} />
<p>Volume actuel : {warHornVolume}%</p>Exemple : Modale
<!-- Modal.svelte -->
<script>
let { open = $bindable(false), title, children } = $props();
function close() {
open = false;
}
</script>
{#if open}
<div class="overlay" role="presentation" onclick={close}>
<div
class="modal"
role="dialog"
aria-modal="true"
tabindex="-1"
onclick={(e) => e.stopPropagation()}
onkeydown={(e) => e.key === 'Escape' && close()}
>
<header>
<h2>{title}</h2>
<button onclick={close}>×</button>
</header>
<main>
{@render children()}
</main>
</div>
</div>
{/if}Un clic sur le fond ferme la fenêtre, et e.stopPropagation() (autrefois le modificateur |stopPropagation) empêche un clic à l'intérieur de la fenêtre d'atteindre le fond.
<!-- Parent.svelte -->
<script>
import Modal from './Modal.svelte';
let showModal = $state(false);
</script>
<button onclick={() => showModal = true}>
Ouvrir la modale
</button>
<Modal bind:open={showModal} title="Conseil de guerre">
<p>Nous préparons une attaque à l'aube !</p>
</Modal>Code de cette leçon : App.svelte
<script>
// $bindable: the child changes the parent's state through bind:value
import CoinCounter from './CoinCounter.svelte';
let treasury = $state({ gold: 10, silver: 25, copper: 40 });
let worth = $derived(treasury.gold * 100 + treasury.silver * 10 + treasury.copper);
</script>
<main class="treasury">
<h1>Viking Treasury</h1>
<p>$bindable props: each counter writes straight into the chest</p>
<div class="counters">
<CoinCounter name="Gold" bind:value={treasury.gold} />
<CoinCounter name="Silver" bind:value={treasury.silver} />
<CoinCounter name="Copper" bind:value={treasury.copper} />
</div>
<div class="total">
<h2>Worth in copper: {worth}</h2>
<button onclick={() => (treasury = { gold: 0, silver: 0, copper: 0 })}>
Empty the chest
</button>
</div>
</main>
<style>
.treasury {
font-family: 'Georgia', serif;
max-width: 600px;
margin: 0 auto;
padding: 2rem;
background: #1a0f0a;
color: #e8d5b7;
min-height: 100vh;
}
h1 {
color: #d4af37;
text-align: center;
}
p {
text-align: center;
color: #8b7355;
}
.counters {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
margin: 2rem 0;
}
.total {
text-align: center;
background: rgba(212, 175, 55, 0.2);
border: 2px solid #d4af37;
border-radius: 8px;
padding: 1rem;
}
.total h2 {
color: #ffd700;
margin: 0 0 0.75rem 0;
}
.total button {
padding: 0.5rem 1rem;
background: #3d2914;
color: #e8d5b7;
border: 1px solid #d4af37;
border-radius: 4px;
cursor: pointer;
}
</style>Entrées de la documentation utilisées dans cette leçon
Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Comment marquer une prop comme bindable dans Svelte 5 ?
Tâches pratiques dans le jeu
- Éditeur de code
Complète le code pour que value soit bindable avec une valeur par défaut de ''