Skip to main content

bind:

D”ordinaire, les données circulent vers le bas, du parent vers ses enfants. La directive bind: permet de faire circuler les données dans l’autre sens, de l’enfant vers le parent.

La syntaxe générale est bind:property={expression}, où expression est une lvalue (c-à-d une variable ou une propriété d’objet). Lorsque l’expression est un identifiant du même nom que la propriété, il est possible d’omettre l’expression — autrement dit ces deux écritures sont équivalentes :

<input bind:value={value} />
<input bind:value />

Svelte crée un gestionnaire d’évènement qui met à jour la valeur liée. Si un élément a déjà un gestionnaire pour le même évènement, ce gestionnaire sera déclenché avant que la valeur liée soit mise à jour.

La plupart des liaisons sont à double sens (two-way), ce qui signifie que toute modification de la valeur va impacter l’élément est vice-versa. Quelques liaisons sont en lecture seule (readonly), ce qui signifie que les changements de valeur n’auront aucun effet sur l’élément.

Liaisons de fonction

Vous pouvez aussi utiliser bind:property={get, set}, où get et set sont des fonctions, vous permettant d’effectuer des validations et des transformations :

<input bind:value={
	() => value,
	(v) => value = v.toLowerCase()}
/>

Dans le cas de liaisons en lecture seule comme dimension bindings, la valeur get doit être null :

<div
	bind:clientWidth={null, redraw}
	bind:clientHeight={null, redraw}
>...</div>

Les liaisons de fonctions sont disponible à partir de Svelte version 5.9.0.

<input bind:value>

Une directive bind:value sur un élément <input> crée une liaison avec la propriété value de l’input :

<script>
	let message = $state('coucou');
</script>

<input bind:value={message} />
<p>{message}</p>

Dans le cas d’un input numérique (type="number" ou type="range"), la valeur sera transformée en nombre (démo) :

<script>
	let a = $state(1);
	let b = $state(2);
</script>

<label>
	<input type="number" bind:value={a} min="0" max="10" />
	<input type="range" bind:value={a} min="0" max="10" />
</label>

<label>
	<input type="number" bind:value={b} min="0" max="10" />
	<input type="range" bind:value={b} min="0" max="10" />
</label>

<p>{a} + {b} = {a + b}</p>

Si l’input est vide ou invalide (dans le cas de type="number"), la valeur sera undefined.

Depuis la version 5.6.0, si un <input> faisant partie d’un formulaire possède une valeur par défaut defaultValue, il récupèrera cette valeur par défaut plutôt que la chaîne de caractères vide lors de la réinitialisation du formulaire. Notez que pour le rendu initial, la valeur de la liaison est prioritaire sauf s’il cette valeur est null ou undefined.

<script>
	let value = $state('');
</script>

<form>
	<input bind:value defaultValue="pas la string vide">
	<input type="reset" value="Réinitialiser">
</form>

Utilisez les boutons de réinitialisation avec prudence, et assurez-vous que les utilisateurs et utilisatrices ne cliquent pas dessus accidentellement lorsqu’ils souhaitent soumettre le formulaire.

<input bind:checked>

Les inputs de type checkbox et radio peuvent être liés avec bind:checked :

<label>
	<input type="checkbox" bind:checked={accepted} />
	Accepter les conditions générales
</label>

Depuis la version 5.6.0, si un <input> faisant partie d’un formulaire possède une valeur par défaut defaultChecked, il récupèrera cette valeur par défaut plutôt que false lors de la réinitialisation du formulaire. Notez que pour le rendu initial, la valeur de la liaison est prioritaire sauf s’il cette valeur est null ou undefined.

<script>
	let checked = $state(true);
</script>

<form>
	<input type="checkbox" bind:checked defaultChecked={true}>
	<input type="reset" value="Réinitialiser">
</form>

<input bind:group>

Les inputs qui fonctionnent en groupe peuvent utiliser bind:group.

<script>
	let tortilla = $state('Nature');

	/** @type {Array<string>} */
	let fillings = $state([]);
</script>

<!-- les inputs radio groupés sont mutuellement exclusifs -->
<input type="radio" bind:group={tortilla} value="Nature" />
<input type="radio" bind:group={tortilla} value="Blé complet" />
<input type="radio" bind:group={tortilla} value="Épinards" />

<!-- les inputs checkbox groupés remplissent un tableau -->
<input type="checkbox" bind:group={fillings} value="Riz" />
<input type="checkbox" bind:group={fillings} value="Haricots" />
<input type="checkbox" bind:group={fillings} value="Fromage" />
<input type="checkbox" bind:group={fillings} value="Guacamole (extra)" />

bind:group ne fonctionne que si les inputs sont dans le même composant Svelte.

<input bind:files>

Vous pouvez utiliser bind:files sur les éléments <input> de type="file" pour obtenir une FileList des fichiers sélectionnés. Lorsque vous souhaitez mettre à jour les fichiers programmatiquement, vous pouvez toujours utiliser un objet FileList. Actuellement les objets FileList ne peuvent pas être construits directement, vous aurez besoin de d’abord créer un nouvel objet DataTransfer et en extraire les files.

<script>
	let files = $state();

	function clear() {
		files = new DataTransfer().files; // null ou undefined ne fonctionne pas
	}
</script>

<label for="avatar">Envoyer une image :</label>
<input accept="image/png, image/jpeg" bind:files id="avatar" name="avatar" type="file" />
<button onclick={clear}>supprimer</button>

Les objets FileList ne peuvent pas non plus être modifiés. Si vous souhaitez par ex. supprimer un fichier de la liste, vous devez créer un nouvel objet DataTransfer et y ajouter uniquement les fichiers que vous souhaitez garder.

DataTransfer peut ne pas être disponible dans certains runtimes JS de serveur. Ne pas initialiser l’état lié aux files permet d’éviter de potentielles erreurs si les composants sont générés côté serveur.

<select bind:value>

Une liaison sur la valeur d’un élément <select> correspond à la propriété value de l’<option> sélectionnée, ce qui peut être n’importe quelle valeur (pas uniquement des chaînes de caractères, comme c’est normalement le cas dans le DOM).

<select bind:value={selected}>
	<option value={a}>a</option>
	<option value={b}>b</option>
	<option value={c}>c</option>
</select>

Un élément <select multiple> se comporte comme un groupe de checkbox. La variable liée est un tableau ayant une entrée correspondant à la propriété value de chaque <option> sélectionnée.

<select multiple bind:value={fillings}>
	<option value="Riz">Riz</option>
	<option value="Haricots">Haricots</option>
	<option value="Fromage">Fromage</option>
	<option value="Guacamole (extra)">Guacamole (extra)</option>
</select>

Lorsque la valeur d’une <option> correspond à son contenu tezte, l’attribut n’est pas nécessaire.

<select multiple bind:value={fillings}>
	<option>Riz</option>
	<option>Haricots</option>
	<option>Fromage</option>
	<option>Guacamole (extra)</option>
</select>

Vous pouvez fournir au <select> une valeur par défaut en ajoutant l’attribut selected à l’<option> (ou à plusieurs <option> dans le cas d’un <select multiple>) qui doit être initialement sélectionnée. Si le <select> fait partie d’un formulaire, il sera réinitialisé à cette séletion initiale lors de la réinitialisation du formulaire. Notez que pour le rendu initial, la valeur de la liaison est prioritaire sauf s’il cette valeur est undefined.

<select bind:value={selected}>
	<option value={a}>a</option>
	<option value={b} selected>b</option>
	<option value={c}>c</option>
</select>

<audio>

Les éléments <audio> ont leur propre jeu de liaisons — cinq à double sens...

... et sept en lecture seule :

<audio src={clip} bind:duration bind:currentTime bind:paused></audio>

<video>

Les éléments <video> ont les mêmes liaisons que les éléments [#audio], auxquels viennent s’ajouter les liaisons en lecture seule videoWidth et videoHeight.

<img>

Les éléments <img> ont deux liaisons en lecture seule :

<details bind:open>

Les éléments <details> acceptent une liaison sur la propriété open.

<details bind:open={isOpen}>
	<summary>Comment réconforter un bug JavaScript ?</summary>
	<p>En le consolant.</p>
</details>

Liaison Contenteditable

Les élément ayant l’attribut contenteditable acceptent les liaisons suivantes :

Il y a des différences subtiles entre innerText et textContent

<div contenteditable="true" bind:innerHTML={html} />

Dimensions

Tous les éléments visibles acceptent les liaisons suivantes en lecture seule, dont les valeurs sont mesurées avec ResizeObserver :

<div bind:offsetWidth={width} bind:offsetHeight={height}>
	<Chart {width} {height} />
</div>

Les éléments display: inline n’ont pas de largeur ou de hauteur (sauf pour les éléments avec des dimensions “intrinsèques”, comme <img> et <canvas>), et ne peuvent pas être observés avec ResizeObserver. Vous aurez besoin de changer le style display de ces éléments à une autre valeur, comme inline-block.

bind:this

bind:this={dom_node}

Pour obtenir la référence d’un noeud du DOM, utilisez bind:this. La valeur liée sera undefined jusqu’à ce que le composant soit monté — autrement dit, vous ne devriez vous servir de cette valeur que dans un effet ou dans un gestionnaire d’évènement, mais pas lors de l’initialisation du composant.

<script>
	/** @type {HTMLCanvasElement} */
	let canvas;

	$effect(() => {
		const ctx = canvas.getContext('2d');
		drawStuff(ctx);
	});
</script>

<canvas bind:this={canvas} />

Les composants acceptent aussi des liaisons bind:this, vous permettant d’interagir programmatiquement avec les instances de composant.

App
<ShoppingCart bind:this={cart} />

<button onclick={() => cart.empty()}> Panier vide </button>
ShoppingCart
<script>
	// Tous les exports d'instance sont accessibles sur l'objet de l'instance
	export function empty() {
		// ...
	}
</script>
<script lang="ts">
	// Tous les exports d'instance sont accessibles sur l'objet de l'instance
	export function empty() {
		// ...
	}
</script>

bind:property pour les composants

bind:property={variable}

Vous pouvez créer des liaisons avec des props de composant en utilisant la même syntaxe que pour les éléments.

<Keypad bind:value={pin} />

Même si les props Svelte sont réactives sans avoir besoin de liaison, cette réactivité est par défaut descendante vers le composant. Utiliser bind:property vous permet de changer la propriété depuis l’intérieur du composant pour faire remonter sa valeur en dehors du composant.

Pour définir une propriété comme acceptant une liaison (bindable), utilisez la rune $bindable :

<script>
	let { propEnLectureSeule, propAcceptantUneLiaison = $bindable() } = $props();
</script>

Déclarer une propriété comme bindable signifie qu’elle peut être utilisée avec bind:, pas qu’elle doit être utilisée avec bind:.

Les propriétés bindables peuvent avoir des valeurs par défaut :

<script>
	let { propAcceptantUneLiaison = $bindable('valeur par défaut') } = $props();
</script>

Cette valeur par défaut s’applique seulement lorsque la propriété n’est pas liée. Si la propriété est liée et une valeur par défaut est définie, le parent se doit de fournir une valeur autre que undefined, sans quoi une erreur de runtime sera levée. Ceci permet d’éviter les situations où il est difficile de comprendre quelle devrait être la bonne valeur utilisée.

Modifier cette page sur Github

précédent suivant