Skip to content
On this page

Select

Base form select.

Usage

Simple Usage

preview
vue
<template>
  <p-select
    :options="options" />
</template>

<script setup>
  const options = ref(['Apple', 'Banana', 'Grape'])
</script>

with Text and Value

preview
vue
<template>
  <p-select
    v-model="value"
    :options="options" />
</template>

<script setup>
  const options = ref([
    { text: '🍎 Apfel', value: 'Apple' },
    { text: '🍇 Traube', value: 'Grape' },
    { text: '🍌 Bananen', value: 'Banana'},
  ])
</script>

with Disabled option

preview
vue
<template>
  <p-select
    v-model="value"
    :options="options" />
</template>

<script setup>
  const options = ref([
    { text: '🍎 Apfel', value: 'Apple' },
    { text: '🍇 Traube', value: 'Grape', disabled: true },
    { text: '🍌 Bananen', value: 'Banana', disabled: false},
  ])
</script>

with Clearable

preview
vue
<template>
  <p-select
    v-model="value"
    :options="options"
    clearable />
</template>

<script setup>
  const options = ref([
    { text: '🍎 Apfel', value: 'Apple' },
    { text: '🍇 Traube', value: 'Grape' },
    { text: '🍌 Bananen', value: 'Banana'},
  ])
</script>

Placeholder

You can set input placeholder via placeholder props

preview
vue
<template>
  <p-select placeholder="Pick A Value" />
</template>

Section Label

You can set sectiom label via section-label props

preview
vue
<template>
  <p-select placeholder="Pick A Value"
    :options="optionsA"
    section-label="Fruits" />
</template>

Sizing

You can set size of select via size prop. Available size are lg, md, sm, xs. Default size is md.

preview
vue
<template>
  <p-select size="xs" v-model="value" :options="options" placeholder="Size xs" />
  <p-select size="sm" v-model="value" :options="options" placeholder="Size sm" />
  <p-select size="md" v-model="value" :options="options" placeholder="Size md" />
  <p-select size="lg" v-model="value" :options="options" placeholder="Size lg" />
</template>

Disabled State

preview
vue
<template>
  <p-select disabled />
</template>

Readonly State

preview
vue
<template>
  <p-select readonly />
</template>

Error State

preview
vue
<template>
  <p-select error />
</template>

Binding v-model

preview

Result :

vue
<template>
  <p-select
    v-model="value"
    :options="options" />
</template>

Binding raw value

If you want to get original selected item (text and value) not value only. you can use v-model:selected.

preview

v-model

-

v-model:selected

-
vue
<template>
  <p-select
    :options="optionsB"
    v-model="value"
    v-model:selected="selected" />
</template>

This component has build-in Fuzzy-search Adapter, powered by Fuze.js.

Example: try type nn, and you'll got Bananen

preview
vue
<template>
  <p-select
    v-model="value"
    :adapter="FuzzyAdapter"
    :options="options" />
</template>

<script setup>
  import { FuzzyAdapter } from '@privyid/persona/core'

  const options = ref([
    { text: '🍎 Apfel', value: 'Apple' },
    { text: '🍇 Traube', value: 'Grape' },
    { text: '🍌 Bananen', value: 'Banana'},
  ])
</script>

Handling Asynchronous

Somecase you will need to load your options from API. You just need define custom async adapter and request handler. It will take care of loading, inifinite load, and other stuff.

preview

Result:

vue
<template>
  <p-select
    :adapter="provincesAdapter"
    v-model="province" />
</template>

<script setup>
  import { defineAsyncAdapter } from "@privyid/persona/core"
  import { getProvinces } from '~/api/region'

  const provincesAdapter = defineAsyncAdapter(async (keyword, page, perPage) => {
    const response = await getProvinces(keyword, page, perPage)

    return response.data.map((item) => {
      return {
        text : item.name,
        value: item.code,
      }
    })
  }, [])
</script>

Reactivity inside Handler

When you working with chaining select like province -> city form. Normally, when you select the province, it should trigger reload on city based on the province. To do this, you need add the province value as watch dependencies. It will automatically reload when province is changed

preview
vue
<template>
  <p-select
    v-model="province"
    placeholder="Select Province"
    :adapter="provincesAdapter"
    @user-input="city = ''" />
  <p-select
    v-model="city"
    placeholder="Select Cities"
    :adapter="citiesAdapter" />
</template>

<script setup>
  import { defineAsyncAdapter } from "@privyid/persona/core"
  import { getProvinces } from '~/api/region'

  const province = ref('')
  const city     = ref('')

  const provincesAdapter = defineAsyncAdapter(/* example above */)

  const citiesAdapter = defineAsyncAdapter(async (keyword, page, perPage) => {
    const response = await getCities(province.value, keyword, page, perPage)
                                    // 👆 reactive ref
    return response.data.map((item) => {
      return {
        text : item.name,
        value: item.id,
      }
    })
  }, [province]) // 👈 need to add `province` as watch deps
</script>

Custom Option with Slot

If you want to make custom option with slot, you can use option with scoped slot. The scoped slot from option has two slot props text and value.

preview
vue
<template>
  <p-select :options="users">
    <template #option="slot">
      <div class="flex flex-row">
        <div class="py-2 pr-3">
          <p-avatar :src="slot.item.value.img" />
          <div class="font-sans text-base font-normal">{{ slot.item.value.img }}
          </div>
            <div class="text-xs font-light option-text">{{ slot.item.text }}
          </div>
        </div>
      </div>
    </template>
  </p-select>
</template>

<script setup>
  const users = ref([
    {
      text: 'John Doe',
      value: {
        img: "https://picsum.photos/id/50/50",
        id: 1
      }
    }
  ])
</script>

Caret

Custom Caret Icon

By using the caret slot-scope, you can define your own custom icon for the caret, giving you the flexibility to choose a different icon or style that suits your design or preference.

preview
vue
<template>
  <p-select :options="optionsA">
    <template #caret="{ isOpen, toggle }">
      <pi-caret-down-16 @click="toggle" />
    </template>
  </p-select>
</template>

<script setup>
  import PiCaretDown16 from '@privyid/persona-icon/vue/caret-down/16.vue'

  const options = ref(['Apple', 'Banana', 'Grape'])
</script>

Hide Caret

When you set the no-caret prop to true, it will hide the caret icon, and users won't see it in the component.

preview
vue
<template>
  <p-select :options="optionsA" />
</template>

<script setup>
  const options = ref(['Apple', 'Banana', 'Grape'])
</script>

API

Props

PropsTypeDefaultDescription
optionsArray-Select option's items
placeholderString-Input placeholder
disabledBooleanfalseDisabled state
readonlyBooleanfalseReadonly state
errorBooleanfalseError state
emptyTextStringNo DataLabel when options is empty
loadingTextStringLoading...Label when loading
adapterAdapterBaseAdapterAdapter for loading option's items
modelValueAny-v-model value
selectedObject-v-model:selected value
no-caretBooleanfalseHide caret icon

Slots

NameDescription
emptyContent when option is empty or not found
loadingContent when loading
optionContent to place in Option Items
caretElement for opening and closing the dropdown

Events

NameArgumentsDescription
changeObjectEvent when value changed
userInputObjectSimilar to change, but it's only triggered when user really clicked the option

See Also

Released under the MIT License.