Skip to content

Data Shape

By default, Vue Pick expects options in a { label, value } shape. If your data comes from an API with different field names (for example { id, name }), you have two options: transform it with .map(), or tell Vue Pick which keys to use.

Default shape

ts
interface OptionItem {
  label: string
  value: any
  disabled?: boolean
  children?: OptionItem[]
}

interface OptionGroup {
  label: string
  disabled?: boolean
  options: OptionItem[]
}

Adapter props

Rather than forcing you to map your data, VPick and VPickNative accept key adapter props:

PropDefaultApplies toDescription
labelKey"label"BothKey for the visible option text.
valueKey"value"BothKey for the emitted v-model value.
disabledKey"disabled"BothKey for the per-option disabled flag.
childrenKey"children"VPick onlyKey for nested children. Options with a non-empty children array enable tree mode.
groupOptionsKey"options"BothKey for the array of options inside a group.

All defaults match the base shape, so existing code keeps working with no changes.

Using custom keys

Your API returns users as { id, name, inactive }? Point Vue Pick at those keys directly. No .map() required.

The same props work on VPickNative:

Groups with custom keys

Groups are detected whenever an item has an array at its groupOptionsKey. Both the group label and its nested options respect labelKey and valueKey.

vue
<script setup>
const regions = [
  {
    name: "Americas",
    members: [
      { id: "us", name: "United States" },
      { id: "ca", name: "Canada" },
    ],
  },
]
</script>

<template>
  <VPick
    :options="regions"
    value-key="id"
    label-key="name"
    group-options-key="members"
  />
</template>

Tree data

Options with a non-empty children array automatically enable tree mode in VPick. No extra prop is needed — the component detects nested data and renders expand/collapse chevrons.

ts
const categories = [
  {
    label: "Electronics",
    value: "electronics",
    children: [
      { label: "Phones", value: "phones" },
      {
        label: "Laptops",
        value: "laptops",
        children: [
          { label: "Gaming", value: "gaming" },
          { label: "Business", value: "business" },
        ],
      },
    ],
  },
  { label: "Books", value: "books" }, // flat items can coexist
]

Flat groups ({ label, options: [] }) and tree nodes ({ label, value, children: [] }) can be mixed at the top level. Empty children: [] is treated as a leaf — no chevron is rendered.

Use childrenKey if your API uses a different key name:

vue
<VPick :options="data" children-key="subcategories" />

Anything beyond key renaming

Vue Pick does not ship function-based adapter props like reduce, normalizer, or getOptionLabel. If you need computed labels or derived values, transform your data in a computed first:

vue
<script setup>
import { computed } from "vue"

const users = ref([...])

const options = computed(() =>
  users.value.map((u) => ({
    label: `${u.firstName} ${u.lastName}`,
    value: u.id,
  }))
)
</script>

<template>
  <VPick :options="options" />
</template>

One line in a computed handles any shape Vue Pick's key props cannot.

Released under the MIT License.