How to pass input value from child component to parent component
If you’re coming from React, passing a value from a child component to the parent component requires some boilerplate code.
You can see an example here.
I’m going to replicate the the example in the link above, but in Svelte.
I’m going to create a Svelte component called input.svelte.
<script>
// Creating a prop
export let onChange;
const handleBlur = e => {
if ('function' === typeof onChange) {
// Pass input value to the top
onChange(e.target.value);
}
};
</script>
<input on:blur={handleBlur}>
In my Input
component, I have a handleBlur()
function. The sole job of this function is to check if onChange
is a function, and if so, pass the input value through.
In my parent Svelte component, App.svelte, I’m going to import my Svelte Input
component, and attach a function handler to the onChange
prop.
<script>
import Input from "./input.svelte";
let fullName = "";
// Update fullName when the value changes on blur event
const handleChange = value => (fullName = value);
</script>
<label>
Enter your name
<Input onChange={handleChange} />
</label>
<h1>Hi {fullName}!</h1>
handleChange()
is responsible to update the state property fullName
.
The greeting message then displays the new name value.
This works fine, but there are 2 problems:
- It doesn’t feel real time because it happens when the input tag is out of focus
- Too much boilerplate code
To solve for the 2 problems above, I can use Svelte bind:property
feature to help our Svelte app stay reactive on change.
Use bind:property instead of handler functions
In Svelte data flows downward. But sometimes you need data to flow upwards to a parent component.
And the example above we did that by tossing event handler functions down, to get values to go up to the parent component.
But, bind:property={variable}
let’s us reduce that boilerplate code, and gives us that real-time update.
It continues to follow the “write less, do more” motto.
Let’s refactor the Input
component and use the bind
property.
<script>
// Input prop called value
export let value;
</script>
<input type="text" bind:value>
The only thing in the <script>
tag is an exported variable called value
.
I’m than updating the input
HTML element to bind with the variable, value
.
Since the export variable name was the same name as the bind property, I used the short-hand version.
<!-- long-hand version -->
<input type="text" bind:value={value}>
<!-- short-hand version -->
<input type="text" bind:value>
Now I’m going to refactor the App.svelte component and make use of the new bind:property
feature.
<script>
import Input from "./input.svelte";
let fullName = "";
</script>
<label>
Enter your name
<input bind:value={fullName}>
</label>
<h1>Hi {fullName}!</h1>
Let’s do a quick breakdown on this file.
I deleted the handler function, handleChange()
, and left the import
statement and the state variable, fullName
.
<script>
import Input from "./input.svelte";
let fullName = "";
</script>
The next update in App.svelte, was the Input
component directive.
<Input bind:value={fullName}>
On the directive, I also added bind:value={fullName}
so it keeps my state variable, fullName
, updated as the user is entering new characters.
Now every time you enter a new character inside the text field, it will update the output greeting message.
I like to tweet about Svelte and post helpful code snippets. Follow me there if you would like some too!