DEV Community

AlbertMarashi for Promatia

Posted on

3 2

Svelte loading state indicator (promises)

Web apps often require loading state (things like loading spinners) to let a user know that an operation is taking place. These operations often take time, so it's best to let the user know something is loading, which helps improve UX and prevents form resubmissions and etc.

We are using this in Promatia and PromaTimes svelte rebuilds.

Add Loading State Indicators to Svelte

REPL: https://svelte.dev/repl/4fefb61253aa4c26b26485e0b2b8c06c?version=3

Imagine you have some UI where a button triggers an async function, and you'd like to display a loading indicator

<script>

async function login(){
  await new Promise(resolve => setTimeout(resolve, 2000) //wait for 2 seconds
}
</script>
<form>
  <button on:click="login">Do thing</button>
</form>

Create an overlay loading indicator

Displays a translucent scrim, with a text loading indicator that goes from . to ...

<div class="LoadingIndicator">
    {text}
</div>
<script>
import { onMount } from 'svelte'
let text = ''

async function loop(){
    if(text.length === 3) text = ''
    text += '.'
    await new Promise(resolve => setTimeout(resolve, 300))
    loop()
}

onMount(()=>{
    loop()
})

</script>
<style>

.LoadingIndicator {
    display: flex;
    background: rgba(0,0,0,0.2);
    justify-content: center;
    align-items: center;
    text-align: center;
    position: absolute; // overlays on top of parent element, parent must have display: relative;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
    z-index: 20;
    font-size: 60px;
}
</style>

Create promiser.js

export default async (promise, subscriber)=>{
    subscriber(true)
    try {
        await promise
    } catch (err) {}
    subscriber(false)
}

Update your form

<script>
import promiser from './promiser.js'
import LoadingIndicator from './LoadingIndicator.svelte'
let loading = false

async function login(){
    return await new Promise(resolve => setTimeout(resolve, 3000))
}

</script>
<div class="form">
    <button on:click={()=>promiser(login(), status => loading = status)}>
        Click me
    </button>
    {#if loading}
    <LoadingIndicator/>
    {/if}
</div>
<style>

    .form {
        position: relative;
        padding: 20px;
    }

</style>

View the REPL: https://svelte.dev/repl/4fefb61253aa4c26b26485e0b2b8c06c?version=3.22.2

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️