Composables
useDialog
[object Object]
Signature
function useDialog(options?: UseDialogOptions): UseDialogResult
Astrazione minima per un dialog: visibilità, stato loading interno, messaggio di errore. Pensato per dialog di conferma + azione async (es. "Sei sicuro?" → POST → chiudi).
Opzioni UseDialogOptions
interface UseDialogOptions {
initialVisible?: boolean
initialLoading?: boolean
initialError?: string | null
}
| Opzione | Tipo | Default |
|---|---|---|
initialVisible | boolean | false |
initialLoading | boolean | false |
initialError | string | null | null |
Risultato UseDialogResult
interface UseDialogResult {
visible: Ref<boolean>
loading: Ref<boolean>
error: Ref<string | null>
hasError: ComputedRef<boolean>
open: () => void
close: () => void
setLoading: (isLoading: boolean) => void
setError: (message: string | null) => void
reset: () => void
}
| Campo | Descrizione |
|---|---|
visible | v-model per <Dialog> |
loading | Stato operazione in corso |
error | Messaggio errore corrente (null se nessuno) |
hasError | computed(() => error.value !== null) |
open() | Imposta visible = true e resetta error = null (parti puliti a ogni apertura) |
close() | Imposta visible = false (non tocca error/loading) |
setLoading(b) | Setter esplicito |
setError(msg) | Setter esplicito (passa null per pulire) |
reset() | Riporta tutti i campi ai valori iniziali |
open() pulisce gli errori: ogni apertura è "fresca". Se vuoi mantenere lo stato di errore tra aperture, gestiscilo manualmente con visible.value = true.Esempio: conferma + azione async
<script setup lang="ts">
import { useMfeContext, useDialog } from '@pzeta/mfe-contracts/composables'
const props = defineProps<{ clienteId: string }>()
const emit = defineEmits<{ deleted: [id: string] }>()
const ctx = useMfeContext()
const dialog = useDialog()
async function confermaElimina() {
dialog.setLoading(true)
dialog.setError(null)
try {
await ctx.http.delete(`/api/clienti/${props.clienteId}`)
dialog.close()
emit('deleted', props.clienteId)
} catch (err) {
dialog.setError(err instanceof Error ? err.message : 'Errore sconosciuto')
} finally {
dialog.setLoading(false)
}
}
</script>
<template>
<button @click="dialog.open">Elimina cliente</button>
<Dialog v-model:visible="dialog.visible.value" header="Conferma eliminazione">
<p>Sei sicuro di voler eliminare questo cliente?</p>
<div v-if="dialog.hasError" class="text-red-600">
⚠ {{ dialog.error.value }}
</div>
<template #footer>
<button @click="dialog.close" :disabled="dialog.loading.value">
Annulla
</button>
<button
@click="confermaElimina"
:disabled="dialog.loading.value"
class="bg-red-600 text-white"
>
{{ dialog.loading.value ? 'Eliminazione...' : 'Elimina' }}
</button>
</template>
</Dialog>
</template>
Pattern: stati multipli con tipo DialogState
interface DialogState {
visible: boolean
loading: boolean
error: string | null
}
Tipo esportato per snapshot del dialog (utile in test o store):
import type { DialogState } from '@pzeta/mfe-contracts'
function getDialogSnapshot(dialog: UseDialogResult): DialogState {
return {
visible: dialog.visible.value,
loading: dialog.loading.value,
error: dialog.error.value,
}
}
Differenza con useDetailForm
| Aspetto | useDialog | useDetailForm |
|---|---|---|
| Scopo | Dialog modale singolo | Form di pagina dettaglio |
| Tracking | visible, loading, error | loading, isFormDirty, canSave |
| Errori | error: Ref<string | null> esposto | Non gestiti (catcha nel chiamante) |
saving() wrapper | No (setter espliciti) | Sì (auto loading on/off) |
| Dirty tracking | No | Sì |
Usa useDialog per dialog isolati (conferma, info, prompt). Usa useDetailForm per pagine di edit con dirty tracking.
Tipi correlati
useDetailFormuseErrorToast— toast suerrorref