DEV Community

myleftshoe
myleftshoe

Posted on

Svelte dialogs - the easy way

The simplest way to create a reusable dialog component using native HTML5 dialogs in svelte!

1) Create Dialog.svelte component:

<script>
    export let dialog
</script>
<dialog bind:this={dialog} on:close>
    <slot/>
</dialog>
Enter fullscreen mode Exit fullscreen mode

Here we export the ref to the native dialog which allows access to its methods by binding to dialog in the parent (below)

on:close simply forwards the native dialog's close event to the parent.

2) Use it in other component:

<script>
    import Dialog from './Dialog.svelte'
    let dialog
</script>

<button on:click={() => dialog.showModal()}>Open It!</button>

<Dialog bind:dialog on:close={() => console.log('closed')}>
    This is amazingly simple! (press esc to close)
</Dialog>
Enter fullscreen mode Exit fullscreen mode

See it working in the REPL!

;)

Top comments (5)

Collapse
 
darenw profile image
Daren Scot Wilson

I'm trying the code shown (after a month away from this project) and do not see a dialog pop up. I get an error: TypeError: Cannot read properties of undefined (reading 'showModal') What is causing this?

Collapse
 
darenw profile image
Daren Scot Wilson

Weird... when I call the component Dialog and name the variable "dialog" it worked! But I'll be needing more than one in my project. Changed the component name, the file's name, import statement, the HTML tag to use Dialog2, still works. Changed the variable name to "dialog2" and its usage in bind: for the element and in the in-line click handler, no syntax errors meaning I didn't miss a stray "dialog" somewhere they're all "dialog2" - but it stops working! Does the variable need to be named "dialog"? If when changed all mentions of it are updated I"d expect it to still work.

Collapse
 
darenw profile image
Daren Scot Wilson

nm.... I had "bind:dialog" originally and changed it to "bind:dialog2" but it should be "bind:dialog={dialog2}"

My brain is slow today!

Collapse
 
darenw profile image
Daren Scot Wilson

If the popup has to show data and has a checkbox or slider to adjust a value, how to convey that data between the main app and the popup?

Collapse
 
myleftshoe profile image
myleftshoe

You would put the content between the Dialog tags, i.e. replace "This is amazingly simple! (press esc to close)" with your own markup. This content is passed into the . For communicating between the parent and child you could forward events to the parent and/or use slot props. Refer to the svelte docs:

learn.svelte.dev/tutorial/slot-props

Having said that, Svelte 5 is replacing slots with snippets. I haven't used it yet, but maybe you jump straight in with svelte 5 because it aims to simplify things.