Components

PickListRemote

Doppia lista per trasferimento elementi con caricamento remoto: spostamento tra lista disponibili e lista selezionati.

Panoramica

PickListRemote è un componente a doppia lista che carica gli elementi disponibili da una sorgente remota e consente di spostarli tra una lista "source" (disponibili) e una lista "target" (selezionati). Il valore emesso è l'array degli elementi nel target.

Caratteristiche principali:

  • Caricamento asincrono elementi disponibili tramite fetchFn
  • Separazione automatica source/target basata su modelValue
  • Spostamento singolo o multiplo con pulsanti freccia
  • Controlli di ordinamento per ogni lista
  • Template personalizzato per la visualizzazione degli elementi
  • Gestione eventi moveToTarget e moveToSource

Casi d'uso tipici: assegnazione utenti a ruoli/gruppi, selezione permessi da assegnare, configurazione colonne visibili, selezione prodotti per un bundle.

Anteprima live (con fetchFn mockato)

Utilizzo nello schema

const schema = [{
  name: 'utentiAssegnati',
  type: 'picklist',
  label: 'Assegna utenti al gruppo',
  props: {
    fetchFn: fetchTuttiUtenti,
    optionLabel: 'nomeCompleto',
    optionValue: 'id',
    sourceTitle: 'Utenti disponibili',
    targetTitle: 'Utenti nel gruppo',
  }
}]

Utilizzo diretto

<PickListRemote
  v-model="utentiAssegnati"
  :fetch-fn="fetchTuttiUtenti"
  option-label="nomeCompleto"
  option-value="id"
  source-title="Utenti disponibili"
  target-title="Utenti assegnati"
  label="Assegnazione utenti"
  @move-to-target="handleAssegna"
  @move-to-source="handleRevoca"
/>

Con template personalizzato

<PickListRemote
  v-model="permessiSelezionati"
  :fetch-fn="fetchPermessi"
  option-value="codice"
  source-title="Permessi disponibili"
  target-title="Permessi assegnati"
>
  <template #option="{ option }">
    <div class="flex items-center gap-2">
      <i :class="option.icona" class="text-blue-500" />
      <div>
        <div class="font-medium">{{ option.nome }}</div>
        <div class="text-xs text-gray-500">{{ option.categoria }}</div>
      </div>
    </div>
  </template>
</PickListRemote>

Come funziona la sincronizzazione source/target

// All'arrivo dei dati da fetchFn:
// - allData = tutti gli elementi dal server
// - modelValue = elementi già nel target
// Il componente calcola:
//   source = allData.filter(item => !targetValues.includes(item[optionValue]))
//   target = modelValue

// Esempio:
// allData = [{id:1, nome:'Mario'}, {id:2, nome:'Luigi'}, {id:3, nome:'Peach'}]
// modelValue = [{id:2, nome:'Luigi'}]
// source = [{id:1, nome:'Mario'}, {id:3, nome:'Peach'}]
// target = [{id:2, nome:'Luigi'}]

Props

PropTipoDefaultDescrizione
modelValueArray<Record<string, unknown>> | null[]Elementi nel target (v-model)
labelstringEtichetta del campo
helperTextstringTesto di supporto sotto il campo
errorstringMessaggio di errore (attiva stato invalid)
disabledbooleanfalseDisabilita il trasferimento
invalidbooleanfalseAttiva visivamente lo stato di errore
fetchFnFetchFnFunzione per caricare tutti gli elementi disponibili
filterstring | FilterCriteriaFiltro statico passato alla fetchFn
optionLabelstring'label'Proprietà da usare come etichetta
optionValuestring'value'Proprietà da usare come identificatore univoco
sourceTitlestring(da i18n: 'Disponibili')Titolo lista sorgente
targetTitlestring(da i18n: 'Selezionati')Titolo lista destinazione
dataKeystring(uguale a optionValue)Chiave univoca per PrimeVue PickList
scrollHeightstring'14rem'Altezza area scrollabile di ogni lista
showSourceControlsbooleantrueMostra pulsanti di ordinamento nella lista source
showTargetControlsbooleantrueMostra pulsanti di ordinamento nella lista target

Slot

SlotPropsDescrizione
sourceheaderHeader lista source (sovrascrive sourceTitle)
targetheaderHeader lista target (sovrascrive targetTitle)
option{ option, index }Template personalizzato per ogni elemento

Metodi esposti

MetodoDescrizione
reload()Ricarica tutti gli elementi chiamando nuovamente la fetchFn

Eventi

EventoPayloadDescrizione
update:modelValueArray<Record<string, unknown>>Elementi aggiornati nel target
moveToTargetArray<Record<string, unknown>>Elementi appena spostati nel target
moveToSourceArray<Record<string, unknown>>Elementi appena spostati nel source

Nota: Gli eventi move-all-to-target e move-all-to-source di PrimeVue vengono internamente mappati su moveToTarget/moveToSource.

Validazione suggerita

import { z } from 'zod'

const schema = z.object({
  utentiAssegnati: z.array(z.object({ id: z.number() }))
    .min(1, 'Assegna almeno un utente')
    .max(10, 'Massimo 10 utenti per gruppo'),
})