I’m using Svelte+Kit for new development, and also starting to use DaisyUI, i found a need to use the Toast component to show a message which appears for a while, then disappears, such as an error message on a form submit, or a success message.
Creating a Svelte component called Toast.svelte would be easy. The challenge is to wrap a callable function to invoke the functionality which would:
- make the Toast visible
- set the message, and the alert style (success, error, etc)
- allow it to disappear after X seconds automatically
To start, i made the simple component, which would have an exported message
and alerttype
props.
<script lang="ts">
export let message = '';
export let alerttype = 'alert-error';
</script>
<div class="toast toast-top toast-start z-40">
{#if message}
<div class="alert {alerttype}">
<div>
<span>{message}</span>
</div>
</div>
{/if}
</div>
That allowed me to invoke the Toast from the parent +page.svelte
like so:
<script lang="ts">
export let toastMessage = 'some error message';
export let toastAlertType = 'alert-error';
</script>
<Toast message={toastMessage} alerttype={toastAlertType} />
Then i could write a page-level function callToast()
, or even a *.ts library, but that was too messy. I want the callable function withing the same Toast.svelte component file.
I did it using the Svelte bind:this element directive.
./components/Toast.svelte
<script lang="ts">
let message = '';
let alerttype = 'alert-error';
// https://akashmittal.com/svelte-calling-function-child-parent/
// call from parent as:
// let toast: Toast;
// toast.callToast(message, alerttype);
// <Toast bind:this={toast} />
export function callToast(msg: string, type?: string|undefined, ms?: number|undefined) {
console.log('callToast()');
let milliseconds: number = 8000;
if(ms) { milliseconds = ms; }
if(type) { alerttype = `alert-${type}`; }
message = msg;
setTimeout(() => {
message = '';
}, milliseconds);
}
</script>
<div class="toast toast-top toast-start z-40">
{#if message}
<div class="alert {alerttype}">
<div>
<span>{message}</span>
</div>
</div>
{/if}
</div>
+page.svelte:
<script lang="ts">
import Toast from "$components/Toast.svelte";
let toast: Toast;
</script>
<Toast bind:this={toast} />
<button on:click={() => toast.callToast('testing this toast notification...', 'error')} class="btn">toast test</button>
Depending on your coding style, this may be easier than using a third-party library.
References:
https://akashmittal.com/svelte-calling-function-child-parent/