DEV Community

Mohamad Harith
Mohamad Harith

Posted on

Workaround for Bubbling Custom Events in Svelte

If you are an avid user of Svelte, you would know by now that we can create custom events in Svelte using the createEventDispatcher method.

However, there is one problem - the current version of Svelte does not bubble the custom events out of the box. As suggested by one of the maintainers of Svelte here, bubbling of custom events in Svelte would probably only be supported in v4 of Svelte. Having said that, event delegation for custom events will not work.

For example, let's say we have a child component, Nested.svelte that dispatches the custom event, my-event and let's say we have a parent component, App.svelte that contains a delegated event listener, listening for the my-event event:

Nested.svelte

<script>
    import {createEventDispatcher} from 'svelte';

    const dispatch = createEventDispatcher();

    const handleClick = ()=>{
        dispatch("my-event", "nested component is clicked")
    }
</script>

<div class="nested" on:click={handleClick}>
    nested component
</div>

<style>
    .nested{
        color:white;
        background-color:blue;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

The following delegated event listener in the App.svelte component would not receive the my-event event because custom events dispatched using Svelte's createEventDispatcher will not bubble.

App.svelte

<script>
    import Nested from "./Nested.svelte";

    document.addEventListener("my-event", (e)=>{
        console.log(e.detail)
    })
</script>

<div class="parent">
    Parent component
    <!--on:my-event is required here so that the event is forwarded-->
    <Nested on:my-event /> 
</div>

<style>
    .parent{
        background-color:yellow;
        padding:10px;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

However, there is a workaround for this issue! We can create our own custom event dispatcher using the Custom Event API like this:

Nested.svelte

<script>
    let ref;

    const handleClick = ()=>{
        const event  = new CustomEvent('my-event', {
            detail: {
                content: 'nested component is clicked'
            }, 
            bubbles: true
        });
        ref.dispatchEvent(event);
    }
</script>

<div class="nested" bind:this={ref} on:click={handleClick}>
    nested component
</div>

<style>
    .nested{
        color:white;
        background-color:blue;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Using the new CustomEvent() constructor, we can create a native custom event and we can also set the bubbles parameter to true to allow the custom event to bubble.

Better yet, my HOD pointed out the custom_event function from svelte/internal. This function wraps Custom Event API and can also be used to dispatch custom events that can bubble:

Nested.svelte

<script>
    import { custom_event } from 'svelte/internal';

    let ref;

    const handleClick = ()=>{
        const event  = custom_event('my-event', 'nested component is clicked', true);
        ref.dispatchEvent(event);
    }
</script>

<div class="nested" bind:this={ref} on:click={handleClick}>
    nested component
</div>

<style>
    .nested{
        color:white;
        background-color:blue;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
patoi profile image
István Pató

In the Svelte source code there is a deprecated code segment, so I think the Custom Event API is the right choice.

Svelte code:
github.com/sveltejs/svelte/blob/62...

Depraction warning:
developer.mozilla.org/en-US/docs/W...