Skip to content

Events are not emitted from components compiled to a custom element #3119

Closed
@vogloblinsky

Description

@vogloblinsky

The native Svelte syntax for listening events on:mycustomevent doesn't works with events dispatched by a Svelte component exported to Custom Element.

May be related to this ?

$on(type, callback) {
// TODO should this delegate to addEventListener?
const callbacks = (this.$$.callbacks[type] || (this.$$.callbacks[type] = []));
callbacks.push(callback);
return () => {
const index = callbacks.indexOf(callback);
if (index !== -1) callbacks.splice(index, 1);
};
}

Here is a reproduction repository :

https://github.com/vogloblinsky/svelte-3-wc-debug

svelte3-raw

Example using just Svelte syntax. Inner component dispatch a custom event 'message'. App component listen to it using on:message

It works !

//Inner.svelte
<script>
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	function sayHello() {
        console.log('sayHello in child: ', 'Hello!');
		dispatch('message', {
			text: 'Hello!'
		});
	}
</script>

<button on:click={sayHello}>
	Click to say hello
</button>
//App.svelte
<script>
	import Inner from './Inner.svelte';

	function handleMessage(event) {
		console.log('handleMessage in parent: ', event.detail.text);
	}
</script>

<Inner on:message={handleMessage}/>

svelte3-wc

Example using just Svelte syntax and exporting component to Web Components. Inner component dispatch a custom event 'message'. App component listen to it using on:message

Same syntax doesn't work.

//Inner.svelte
<svelte:options tag="inner-btn"/>
<script>
	import { createEventDispatcher } from 'svelte';

	const dispatch = createEventDispatcher();

	function sayHello() {
        console.log('sayHello in child: ', 'Hello!');
		dispatch('message', {
			text: 'Hello!'
		});
	}
</script>

<button on:click={sayHello}>
	Click to say hello
</button>
//App.svelte
<svelte:options tag="my-app" />
<script>
	import Inner from './Inner.svelte';

	function handleMessage(event) {
		console.log('handleMessage in parent: ', event.detail.text);
	}
</script>

<inner-btn on:message={handleMessage}/>

Vanilla JS works fine in public/index.html

const button = document
                    .querySelector('my-app')
                    .shadowRoot.querySelector('inner-btn');

                button.$on('message', e => {
                    console.log('handleMessage in page');
                });

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions