Components

DynamicFormDrawer

Drawer laterale con form dinamico per creazione/modifica record con autoload remoto.

Panoramica

DynamicFormDrawer apre un drawer laterale (PrimeVue Drawer) contenente un DynamicFormLayouts. A differenza di DynamicFormDialog, supporta:

  • Posizione configurabile: left, right, top, bottom
  • Auto-fetch del record: se passi keyValue + fetchFn, il drawer carica automaticamente i dati alla apertura
  • Dimensione configurabile: tramite la prop size del Drawer di @pzeta/vue-components (small / medium / large / full)

Casi d'uso tipici:

  • Modifica record cliccando una riga di una lista, senza navigazione
  • Form di dettaglio scivola da destra mantenendo visibile la lista
  • Wizard di creazione multi-step con displayMode="wizard"

Anteprima live (con createFn mockato)

Utilizzo

Creazione

<!-- Codice reale con API -->
<script setup lang="ts">
import { ref } from 'vue'
import { DynamicFormDrawer } from '@pzeta/vue-form'

const showDrawer = ref(false)

const schema = {
  sections: [
    {
      title: 'Nuovo utente',
      rows: [
        {
          fields: [
            { name: 'nome', type: 'text', label: 'Nome', validation: 'required', required: true },
            { name: 'cognome', type: 'text', label: 'Cognome', validation: 'required', required: true }
          ]
        },
        {
          fields: [
            { name: 'email', type: 'email', label: 'Email', validation: 'required|email', required: true }
          ]
        }
      ]
    }
  ]
}

async function handleCreate(data: Record<string, unknown>) {
  return api.createUtente(data)
}
</script>

<template>
  <Button label="Nuovo utente" icon="pi pi-plus" @click="showDrawer = true" />

  <DynamicFormDrawer
    v-model:visible="showDrawer"
    :schema="schema"
    :is-edit="false"
    :create-fn="handleCreate"
    header="Nuovo utente"
    position="right"
    size="medium"
  />
</template>

Modifica con auto-fetch

<!-- Codice reale con API -->
<script setup lang="ts">
import { ref } from 'vue'
import { DynamicFormDrawer } from '@pzeta/vue-form'

const showDrawer = ref(false)
const utenteSelezionatoId = ref<number | null>(null)

async function fetchUtente(id: string | number) {
  const response = await fetch(`/api/utenti/${id}`)
  return response.json()
}

async function updateUtente(id: string | number, data: Record<string, unknown>) {
  const response = await fetch(`/api/utenti/${id}`, {
    method: 'PUT',
    body: JSON.stringify(data)
  })
  return response.json()
}

function modifica(id: number) {
  utenteSelezionatoId.value = id
  showDrawer.value = true
}
</script>

<template>
  <Button label="Modifica" icon="pi pi-pencil" @click="modifica(42)" />

  <DynamicFormDrawer
    v-model:visible="showDrawer"
    :schema="schema"
    :is-edit="true"
    :key-value="utenteSelezionatoId ?? undefined"
    :fetch-fn="fetchUtente"
    :update-fn="updateUtente"
    header="Modifica utente"
    position="right"
  />
</template>

Quando isEdit=true + keyValue + fetchFn sono presenti, il drawer chiama fetchFn(keyValue) all'apertura e popola initialData con il risultato.

Props

PropTipoDefaultDescrizione
visiblebooleanVisibilità drawer (v-model:visible)
schemaFormSchemaSchema del form
displayMode'normal' | 'tabs' | 'wizard' | 'accordion''normal'Modalità del DynamicFormLayouts interno
isEditbooleanfalseModalità modifica (vs creazione)
initialDataRecord<string, unknown>{}Dati iniziali (sovrascritti da fetchFn se presente)
position'left' | 'right' | 'top' | 'bottom''right'Posizione del drawer
headerstring''Titolo header drawer
size'small' | 'medium' | 'large' | 'full''medium'Dimensione del drawer (mappa alla prop size del Drawer di @pzeta/vue-components)
keyValuestring | number''ID del record per la modalità modifica
fetchFn(id) => Promise<Record<string, unknown>>Funzione di fetch del record per la modifica
createFn(data) => Promise<Record<string, unknown>>Funzione di creazione
updateFn(id, data) => Promise<Record<string, unknown>>Funzione di aggiornamento
drawerClassstringDeprecata e non funzionante: il Drawer di @pzeta/vue-components usa <Teleport> e non eredita l'attributo class. Usare size. Verrà rimossa in una major successiva

Eventi

EventoPayloadDescrizione
update:visiblebooleanCambio visibilità (compatibile v-model:visible). Emesso a false su click X o overlay
saveRecord<string, unknown>Submit completato. Payload: dirtyValues in modalità isEdit, altrimenti formData completo
update:initial-dataRecord<string, unknown>Emesso dopo fetchFn (load record) o dopo createFn/updateFn (record salvato/ricaricato). Utile per sincronizzare lo stato del parent
errorErrorErrore in fetch/create/update

Differenza con DynamicFormDrawerWithTable

AspettoDynamicFormDrawerDynamicFormDrawerWithTable
Lista record❌ — solo form di un singolo record✅ — tabella + form integrati
Auto-fetch del record✅ via fetchFn(keyValue)✅ via fetchAllFn(filters) per la lista
Operazioni delete✅ via deleteFn
Quando usarloForm di dettaglio standalonePannello completo CRUD entità