The structure of my application is as follows:
In the child component I want to pass data up to the Grandparent, depending on which result the user clicks on. I tried doing this, using an Event Dispatcher. This unfortunately fails, as it seems that communication is only possible between parent and child. Is there a way to accomplish this?
This here is my (simplified) code:
// Grandparent
<form on:submit|preventDefault={handleSubmit}>
<Search bind:item={item} on:result={e => console.log(e)} />
</form>
// Parent
<div class="search-results">
<Response data={res} />
</div>
// Child
<script>
function returnData(data) {
dispatch("result", data);
}
</script>
<button on:click={() => returnData(data)}>Click</button>
In Svelte 3 and 4 you can bubble events by using on:<eventName>
without any event handler afterwards:
// Grandparent
<form on:submit|preventDefault={handleSubmit}>
<Search bind:item={item} on:result={e => console.log(e)} />
</form>
// Parent
<div class="search-results">
<!-- only this line changes in your code:
bubble the result event -->
<Response data={res} on:result />
</div>
// Child
<script>
function returnData(data) {
dispatch("result", data);
}
</script>
<button on:click={() => returnData(data)}>Click</button>
In Svelte 5, use callback props instead, and pass them down (e.g. create a onresult
prop for Parent and Child):
// Grandparent
<form onsubmit={handleSubmit}>
<Search bind:item={item} onresult={e => console.log(e)} />
</form>
// Parent
<script>
let { item = $bindable(), onresult } = $props();
</script>
<div class="search-results">
<Response data={res} {onresult} />
</div>
// Child
<script>
let { onresult } = $props();
</script>
<button onclick={() => onresult(data)}>Click</button>