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>
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>
See it working in the REPL!
;)
Top comments (5)
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?
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.
nm.... I had "bind:dialog" originally and changed it to "bind:dialog2" but it should be "bind:dialog={dialog2}"
My brain is slow today!
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?
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.