Svelte and SvelteKit course ยท Module 10: Actions
Updating Parameters
In this lesson3
update() - React to parameter changes
An action is called only once. When the parameter changes, Svelte does not call it again - instead it calls the update() method of the returned object with the new value:
export function tooltip(node, text) {
let tooltipEl;
let currentText = text;
// ... show/hide logic
return {
update(newText) {
currentText = newText;
if (tooltipEl) {
tooltipEl.textContent = newText;
}
},
destroy() {
// cleanup
}
};
}<script>
import { tooltip } from './actions.js';
let message = $state('Initial text');
</script>
<input bind:value={message} />
<button use:tooltip={message}>
Hover me
</button>Object as parameter
export function draggable(node, options = {}) {
let { axis = 'both', bounds = null } = options;
// ... logic
return {
update(newOptions) {
axis = newOptions.axis ?? 'both';
bounds = newOptions.bounds ?? null;
},
destroy() {
// cleanup
}
};
}<div use:draggable={{ axis: 'x', bounds: 'parent' }}>
Drag me horizontally
</div>New: attachments ({@attach})
Since Svelte 5.29 you can use attachments instead of actions. An attachment is a function that receives the element and may return a cleanup function. Unlike an action it is fully reactive: when state used in its call changes, Svelte cleans it up and runs it again, so you do not need update().
<script>
let message = $state('Initial text');
function tooltip(text) {
return (node) => {
node.title = text;
return () => node.removeAttribute('title');
};
}
</script>
<input bind:value={message} />
<button {@attach tooltip(message)}>Hover over me</button>Actions (use:) are still fully supported and you will find them in many libraries, which is why this location practises them.
Code for this lesson: App.svelte
<script>
// Actions with events - click outside, longpress
import { clickOutside } from './actions.js';
import { longpress } from './actions.js';
let modalOpen = $state(false);
let message = $state('');
function handleClickOutside() {
modalOpen = false;
}
function handleLongpress() {
message = 'Long press detected!';
setTimeout(() => message = '', 2000);
}
</script>
<main class="actions-demo">
<h1>Actions with events</h1>
<section>
<h2>use:clickOutside</h2>
<button onclick={() => modalOpen = true}>Open modal</button>
{#if modalOpen}
<div class="overlay">
<div class="modal" use:clickOutside onoutclick={handleClickOutside}>
<h3>Modal</h3>
<p>Click outside me to close</p>
</div>
</div>
{/if}
</section>
<section>
<h2>use:longpress</h2>
<button
use:longpress={500}
onlongpress={handleLongpress}
>
Hold 500ms
</button>
{#if message}
<p class="message">{message}</p>
{/if}
</section>
</main>
<style>
.actions-demo {
font-family: 'Georgia', serif;
max-width: 500px;
margin: 0 auto;
padding: 2rem;
background: #1a1a2e;
color: #e8e8f7;
min-height: 100vh;
}
h1 {
color: #7cb3f0;
text-align: center;
}
section {
background: rgba(124, 179, 240, 0.1);
border: 1px solid #7cb3f0;
border-radius: 8px;
padding: 1rem;
margin: 1rem 0;
}
h2 {
color: #7cb3f0;
font-size: 1rem;
margin-top: 0;
}
button {
padding: 0.75rem 1.5rem;
background: #3a5f8a;
color: #e8e8f7;
border: 1px solid #7cb3f0;
border-radius: 4px;
cursor: pointer;
}
.overlay {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.7);
display: flex;
align-items: center;
justify-content: center;
z-index: 100;
}
.modal {
background: #16213e;
border: 2px solid #7cb3f0;
border-radius: 8px;
padding: 2rem;
min-width: 300px;
text-align: center;
}
.modal h3 {
color: #7cb3f0;
margin-top: 0;
}
.message {
margin-top: 0.5rem;
padding: 0.5rem;
background: rgba(255, 215, 0, 0.2);
border-radius: 4px;
color: #ffd700;
}
</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. Which method in the object returned from an action responds to parameter changes?