Svelte and SvelteKit course ยท Module 5: Bindings
bind:this - DOM References
In this lesson5
bind:this gives access to a DOM element - like grasping the Bifrost bridge!
Basic Usage
<script>
let inputElement;
function focusInput() {
inputElement.focus();
}
</script>
<input bind:this={inputElement} placeholder="Click the button..." />
<button onclick={focusInput}>Focus on input</button>Canvas
<script>
import { onMount } from 'svelte';
let canvas;
onMount(() => {
const ctx = canvas.getContext('2d');
// Draw a rune
ctx.fillStyle = 'gold';
ctx.font = '48px serif';
ctx.fillText('แฑ', 50, 60);
});
</script>
<canvas bind:this={canvas} width="200" height="100"></canvas>Audio and Video
<script>
let audio;
let isPlaying = $state(false);
let currentTime = $state(0);
let duration = $state(0);
function togglePlay() {
if (isPlaying) {
audio.pause();
} else {
audio.play();
}
isPlaying = !isPlaying;
}
</script>
<audio
bind:this={audio}
bind:currentTime
bind:duration
src="/horn.mp3"
></audio>
<button onclick={togglePlay}>
{isPlaying ? 'Pause' : 'Play'}
</button>
<p>Time: {Math.floor(currentTime)} / {Math.floor(duration)}</p>bind:this with Components
<script>
import WarriorPanel from './WarriorPanel.svelte';
let panel;
function openPanel() {
panel.open(); // Call a component method
}
</script>
<WarriorPanel bind:this={panel} />
<button onclick={openPanel}>Open panel</button><!-- WarriorPanel.svelte -->
<script>
let isOpen = $state(false);
export function open() {
isOpen = true;
}
export function close() {
isOpen = false;
}
</script>
{#if isOpen}
<div class="panel">
Warrior panel
<button onclick={close}>Close</button>
</div>
{/if}bind:value with Your Own Component ($bindable)
bind: also works with your components, but only on props marked with $bindable() (you met them in Asgard, in module 4). The component declares such a prop, and the parent binds it with bind:value:
<!-- Slider.svelte -->
<script>
let { value = $bindable(50), label = '' } = $props();
</script>
<label>
{label}: {value}
<input type="range" min="0" max="100" bind:value />
</label><!-- App.svelte -->
<script>
import Slider from './Slider.svelte';
let health = $state(100);
</script>
<Slider bind:value={health} label="Health" />
<p>Warrior health: {health}</p>Moving the slider changes health in the parent. Without $bindable() such a bind:value ends in an error - the prop then flows only from parent to child. In the editor below, Slider and TextInput work the same way.
Code for this lesson: App.svelte
<script>
// Svelte 5: $bindable() - bindable props
import Slider from './Slider.svelte';
import TextInput from './TextInput.svelte';
let health = $state(100);
let strength = $state(75);
let warriorName = $state('Ragnar');
</script>
<main class="stats-panel">
<h1>Stats Panel</h1>
<p class="subtitle">Svelte 5: $bindable() props</p>
<section>
<h2>Warrior name</h2>
<TextInput bind:value={warriorName} label="Name" />
<p>Hello, <strong>{warriorName}</strong>!</p>
</section>
<section>
<h2>Stats</h2>
<Slider
bind:value={health}
label="Health"
color="#ff4444"
/>
<Slider
bind:value={strength}
label="Strength"
color="#ffd700"
/>
</section>
<div class="preview">
<h2>{warriorName}</h2>
<div class="stat">
<span>{health}</span>
<span>{strength}</span>
</div>
<p class="total">Total power: {health + strength}</p>
</div>
</main>
<style>
.stats-panel {
font-family: 'Georgia', serif;
max-width: 500px;
margin: 0 auto;
padding: 2rem;
background: #1a0f0a;
color: #e8d5b7;
min-height: 100vh;
}
h1 {
color: #d4af37;
text-align: center;
}
.subtitle {
text-align: center;
color: #8b7355;
}
section {
background: rgba(212, 175, 55, 0.1);
border: 1px solid #d4af37;
border-radius: 8px;
padding: 1rem;
margin: 1rem 0;
}
h2 {
color: #d4af37;
font-size: 1rem;
margin-top: 0;
}
strong {
color: #ffd700;
}
.preview {
background: rgba(255, 215, 0, 0.1);
border: 2px solid #ffd700;
border-radius: 8px;
padding: 1.5rem;
text-align: center;
}
.preview h2 {
color: #ffd700;
font-size: 1.5rem;
margin: 0;
}
.stat {
display: flex;
justify-content: center;
gap: 2rem;
margin: 1rem 0;
font-size: 1.25rem;
}
.total {
color: #b19cd9;
font-size: 1rem;
}
</style>Docs entries used in this lesson
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What is bind:this used for?
Hands-on tasks in the game
- Code editor
Complete the code to get a reference to the canvas - onMount then draws a rune on it