Add auto loading state for `UButton`/`UForm`
Description
Currently, there is no built-in way to set a auto loading state for buttons in nuxt/ui when they are linked to a @click event or are the submit button of a UForm.
Proposal
Add a feature to nuxt/ui to enable a loading state for buttons. This should be configurable for:
- Buttons with
@clickevents. - Submit buttons of a
UFormwith a reference to the form.
This enhancement will improve user experience by preventing multiple submissions and indicating that an action is in progress.
Example
<UButton promise-loading @click="handleClick">
Submit
</UButton>
<UForm ref="myForm" @submit="handleSubmit">
<UButton :loading="myForm.promiseLoading" type="submit">
Submit
</UButton>
</UForm>
Benefits
- Prevents multiple submissions.
- Provides a better DX.
Additional context
No response
I like the idea, but i think it would be a bit tricky since we don't have access to any information about event handlers using emits and can't really wait for it to resolve. (For example here: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Form.vue#L136).
The only solution I can think of is to replace the @submit / @click events by a prop with a callback function, but it feels a bit odd.
A dedicated composable maybe? Something like useAsyncData except in only returns a handle to execute the function and the loading state?
const { loading, execute: submit } = useLoading(async () => { /* ... */ })
This can be achieved using VueUse's useAsyncState (https://vueuse.org/core/useAsyncState/) to wrap your event handlers:
const { isReady, execute } = useAsyncState(async () => {
// ...
},
null,
{ immediate: false },
)
I found out that we can declare emits using props while exploring ways to implement this, so it's actually possible to do it without changing the way components are used 😄
Here's a sample implementation for v3: https://github.com/benjamincanac/ui3/pull/135/files
So cool 🤩