Workaround for Bubbling Custom Events in Svelte
Tags: svelte, javascript
Published: 2021-12-25 18:59:39

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](https://github.com/sveltejs/svelte/pull/4599#issuecomment-830336280), 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**
```html
<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>
```
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**
```html
<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>
```

However, there is a workaround for this issue! We can create our own custom event dispatcher using the [Custom Event API](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent) like this: 

**Nested.svelte**
```html
<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>
```
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](https://github.com/si3nloong) pointed out the `custom_event` function from `svelte/internal`. This function wraps [Custom Event API](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent) and can also be used to dispatch custom events that can bubble: 

**Nested.svelte**
```html
<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>
```