useAsyncOptions
useAsyncOptions fetches a list of { label, value } options for use in selects, dropdowns, and comboboxes. It wraps the fetcher with reactive options, loading, error, and reload state.
Signature
ts
interface SelectOption<T = string | number> {
label: string
value: T
disabled?: boolean
[key: string]: unknown
}
function useAsyncOptions<T = string | number>(
fetcher: () => Promise<SelectOption<T>[]>,
opts?: { immediate?: boolean }
): {
options: Ref<SelectOption<T>[]>
loading: Ref<boolean>
error: Ref<string | null>
reload: () => Promise<void>
}Basic usage
ts
import { useAsyncOptions } from '@jetpack-labs/jetpack-ui'
import api from '@/axios'
const { options: productOptions, loading } = useAsyncOptions(() =>
api.get('/api/v1/products').then(r =>
r.data.map(p => ({ label: p.name, value: p.id }))
)
)vue
<template>
<select v-if="!loading">
<option
v-for="opt in productOptions"
:key="opt.value"
:value="opt.value"
:disabled="opt.disabled"
>
{{ opt.label }}
</option>
</select>
</template>With typed value
Use the generic parameter for non-string/number values:
ts
interface Customer { id: number; name: string }
const { options } = useAsyncOptions<number>(() =>
api.get('/api/v1/customers').then(r =>
r.data.map((c: Customer) => ({ label: c.name, value: c.id }))
)
)
// options is Ref<SelectOption<number>[]>Deferred fetch
ts
const { options, reload } = useAsyncOptions(
() => api.get('/api/v1/cost-centers').then(r =>
r.data.map(c => ({ label: c.name, value: c.id }))
),
{ immediate: false }
)
// trigger when needed
onMounted(() => reload())Disabled options
Include disabled: true in any option object to disable that option:
ts
const { options } = useAsyncOptions(() =>
api.get('/api/v1/shifts').then(r =>
r.data.map(s => ({
label: s.name,
value: s.id,
disabled: s.locked,
}))
)
)Error handling
If the fetcher throws, error is set and options resets to an empty array []. The error is cleared on the next reload().
Return values
| Key | Type | Description |
|---|---|---|
options | Ref<SelectOption<T>[]> | The resolved option list (empty array while loading) |
loading | Ref<boolean> | true while the fetcher is running |
error | Ref<string | null> | Error message, or null |
reload | () => Promise<void> | Re-runs the fetcher |
SelectOption interface
ts
interface SelectOption<T = string | number> {
label: string // display text
value: T // bound value
disabled?: boolean // disables the option
[key: string]: unknown // extra metadata passthrough
}This interface is exported from the package:
ts
import type { SelectOption } from '@jetpack-labs/jetpack-ui'