In Svelte, data flow is generally one-directional—from parent to child. However, there are times when we need to pass data from child to parent, and we can use custom events for this. Another convenient way to synchronize data between child and parent is through two-way binding. This allows the parent to maintain control over the data, while the child updates it.
In this blog post, we will explore two methods for passing data from child to parent: using custom events and using two-way binding.
Method 1: Passing Data with Custom Events
Let's first see how to pass data from a child to a parent using custom events. In this scenario, we will use a simple counter component that sends updated count data to the parent component.
Step 1: The Child Component
In the child component (Counter.svelte
), we define a counter and use Svelte's createEventDispatcher
to emit an event to the parent when the count is updated.
<script>
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
let count = 0;
function increment() {
count += 1;
dispatch('increment', { count });
}
</script>
<button on:click={increment}>
Count: {count}
</button>
Step 2: The Parent Component
In the parent component, we listen for the custom increment
event and update the parent's state accordingly.
<script>
let totalCount = 0;
function handleIncrement(event) {
totalCount = event.detail.count;
}
</script>
<h1>Total Count: {totalCount}</h1>
<Counter on:increment={handleIncrement} />
Method 2: Two-Way Binding
Another approach to pass data between child and parent components is by using two-way binding. This allows the parent component to directly bind a variable to the child component's property, and any changes in the child will automatically update the parent.
Let's see how this works with an example where we bind a name property between parent and child components.
Step 1: The Child Component (Box.svelte
)
Here, the child component accepts a person
prop, which is bound to a parent variable using bind:
syntax.
<script>
export let person;
</script>
<input bind:value={person} placeholder="Enter your name" />
Step 2: The Parent Component
In the parent component, we declare a variable p
and bind it to the person
prop in the Box
component. We also create a reactive statement to display the uppercase version of the name.
<script>
import Box from './Box.svelte';
let p = 'MyName';
// Reactive statement to compute the uppercase version of p
$: nameUpper = p.toUpperCase();
</script>
<!-- Bind p to person in the child component -->
<Box bind:person={p} />
<p>Reactive value in the parent component: {nameUpper}</p>
<hr />
Explanation
Reactive Statement: We use the reactive
$:
syntax in Svelte to automatically update thenameUpper
variable wheneverp
changes.Two-Way Binding: By using the
bind:
directive in the parent (<Box bind:person={p} />
), any change in the child component'sperson
prop will automatically updatep
in the parent.
Example in Action:
Initially, the parent
p
is set to"MyName"
. This is passed to the child, and the input box displays"MyName"
.When you type a new name in the input box, the
person
variable in the child updates, which also updatesp
in the parent. This change triggers the reactive statement$: nameUpper = p.toUpperCase()
in the parent, and the uppercase name is displayed in real-time.
Conclusion
By using custom events and two-way binding, you can easily pass data from child to parent components in Svelte. For more complex or multi-component data sharing, you can consider using stores. However, for simple parent-child communication, these techniques are effective and easy to implement.
In summary:
Use custom events when you need to notify the parent of a change in the child component.
Use two-way binding when you want to directly synchronize a variable between the parent and child.
Top comments (2)
Unsure if your bias for React (as seen in your bio) affected the outcome of the article or not, but Svelte has more than just these. The most obvious one missing here is Svelte stores, for which React has no equivalent (React provides no global state management).
Then there's context, where anything can be stored, including a specialized class that allows bi-directional communication.
Then there's Svelte v5 soon to come out. Version 5 uses signals and true fine-grain reactivity, making communication simpler by adding native reactivity.
Leaving this here for readers to come.
Thank you for the info. I am going cover as soon as possible these in next blog.😊