Skip to content

Select

CSelect is used to choose an item from a collection of options.

Basic Usage

CSelect is used with the v-model property for two-way value binding along with the options collection. Label and value of an option are defined with the optionLabel and optionValue properties respectively.

TIP

When options are simple primitive values such as a string array, no optionLabel and optionValue would be necessary.

vue

<template>
  <div class="card flex justify-center">
    <CSelect 
        v-model="selectedCity" 
        :options="cities" 
        optionLabel="name" 
        placeholder="Select a City" 
        class="w-full md:w-56" 
    />
  </div>
</template>

<script setup lang="ts">
  import { ref } from 'vue';

  const selectedCity = ref(null);
  const cities = ref([
    { name: 'New York', code: 'NY' },
    { name: 'Rome', code: 'RM' },
    { name: 'London', code: 'LDN' },
    { name: 'Istanbul', code: 'IST' },
    { name: 'Paris', code: 'PRS' }
  ]);
</script>

Checkmark

An alternative way to highlight the selected option is displaying a checkmark instead.

vue
<template>
  <CSelect 
      v-model="selectedCity" 
      :options="cities" 
      optionLabel="name" 
      placeholder="Select a City" 
      checkmark 
      class="w-full md:w-56" 
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const selectedCity = ref(null);
const cities = ref([
    { name: 'New York', code: 'NY' },
    { name: 'Rome', code: 'RM' },
    { name: 'London', code: 'LDN' },
    { name: 'Istanbul', code: 'IST' },
    { name: 'Paris', code: 'PRS' }
]);
</script>

Editable

When editable is present, the input can also be entered with typing.

vue
<template>
  <CSelect 
      v-model="selectedCity" 
      editable 
      :options="cities" 
      optionLabel="name" 
      placeholder="Select a City" 
      class="w-full md:w-56" 
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const selectedCity = ref(null);
const cities = ref([
    { name: 'New York', code: 'NY' },
    { name: 'Rome', code: 'RM' },
    { name: 'London', code: 'LDN' },
    { name: 'Istanbul', code: 'IST' },
    { name: 'Paris', code: 'PRS' }
]);
</script>

Group

Options can be grouped when a nested data structures is provided. To define the label of a group optionGroupLabel property is needed and also optionGroupChildren is required to define the property that refers to the children of a group.

vue
<template>
  <CSelect 
      v-model="selectedCity" 
      :options="groupedCities" 
      optionLabel="label" 
      optionGroupLabel="label" 
      optionGroupChildren="items" 
      placeholder="Select a City" 
      class="w-full md:w-56"
  >
    <template #optiongroup="slotProps">
      <div class="flex items-center gap-2">
        <span class="fi w-5" :class="[`fi-${slotProps.option.code.toLowerCase()}`]"></span>
        <div>{{ slotProps.option.label }}</div>
      </div>
    </template>
  </CSelect>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const selectedCity = ref();
const groupedCities = ref([
    {
        label: 'Germany',
        code: 'DE',
        items: [
            { label: 'Berlin', value: 'Berlin' },
            { label: 'Frankfurt', value: 'Frankfurt' },
            { label: 'Hamburg', value: 'Hamburg' },
            { label: 'Munich', value: 'Munich' }
        ]
    },
    {
        label: 'USA',
        code: 'US',
        items: [
            { label: 'Chicago', value: 'Chicago' },
            { label: 'Los Angeles', value: 'Los Angeles' },
            { label: 'New York', value: 'New York' },
            { label: 'San Francisco', value: 'San Francisco' }
        ]
    },
    {
        label: 'Japan',
        code: 'JP',
        items: [
            { label: 'Kyoto', value: 'Kyoto' },
            { label: 'Osaka', value: 'Osaka' },
            { label: 'Tokyo', value: 'Tokyo' },
            { label: 'Yokohama', value: 'Yokohama' }
        ]
    }
]);
</script>

Template

CSelect provides templating options to customize the different sections of the component.

Value

The value slot is used to customize the content of the selected item. The slot props include value, which correspond to the selected value, and placeholder properties.

Option

The option slot is used to customize the content of options. The slot props include option property which is the complete object of the current option.

The dropdownicon slot is used to customize the dropdown icon.

The header and footer slots are used to add custom content at the top and bottom of the overlay panel.

vue
<template>
  <CSelect 
      v-model="selectedCountry" 
      :options="countries" 
      optionLabel="name" 
      placeholder="Select a Country" 
      class="w-full md:w-56"
  >
    <template #value="slotProps">
        <div v-if="slotProps.value" class="flex items-center gap-2">
            <span class="fi w-5" :class="[`fi-${slotProps.value.code.toLowerCase()}`]"></span>
            <div>{{ slotProps.value.name }}</div>
        </div>
        <span v-else>
            {{ slotProps.placeholder }}
        </span>
    </template>
    <template #option="slotProps">
      <div class="flex items-center gap-2">
        <span class="fi w-5" :class="[`fi-${slotProps.option.code.toLowerCase()}`]"></span>
        <div>{{ slotProps.option.name }}</div>
      </div>
    </template>
    <template #dropdownicon>
      <i class="pi pi-map" />
    </template>
    <template #header>
      <div class="font-medium p-3">Available Countries</div>
    </template>
    <template #footer>
      <div class="p-3">
        <CButton label="Add New" fluid severity="secondary" text icon="pi pi-plus" />
      </div>
    </template>
  </CSelect>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const selectedCountry = ref();
const countries = ref([
    { name: 'Australia', code: 'AU' },
    { name: 'Brazil', code: 'BR' },
    { name: 'China', code: 'CN' },
    { name: 'Egypt', code: 'EG' },
    { name: 'France', code: 'FR' },
    { name: 'Germany', code: 'DE' },
    { name: 'India', code: 'IN' },
    { name: 'Japan', code: 'JP' },
    { name: 'Spain', code: 'ES' },
    { name: 'United States', code: 'US' }
]);
</script>

Filter

CSelect provides built-in filtering that is enabled by adding the filter property.

vue

<template>
  <CSelect
      v-model="selectedCountry"
      :options="countries"
      filter
      optionLabel="name"
      placeholder="Select a Country"
      class="w-full md:w-56"
  >
    <template #value="slotProps">
      <div v-if="slotProps.value" class="flex items-center gap-2">
        <span class="fi w-5" :class="[`fi-${slotProps.value.code.toLowerCase()}`]"></span>
        <div>{{ slotProps.value.name }}</div>
      </div>
      <span v-else>
                    {{ slotProps.placeholder }}
                </span>
    </template>
    <template #option="slotProps">
      <div class="flex items-center gap-2">
        <span class="fi w-5" :class="[`fi-${slotProps.option.code.toLowerCase()}`]"></span>
        <div>{{ slotProps.option.name }}</div>
      </div>
    </template>
  </CSelect>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const selectedCountry = ref();
const countries = ref([
    { name: 'Australia', code: 'AU' },
    { name: 'Brazil', code: 'BR' },
    { name: 'China', code: 'CN' },
    { name: 'Egypt', code: 'EG' },
    { name: 'France', code: 'FR' },
    { name: 'Germany', code: 'DE' },
    { name: 'India', code: 'IN' },
    { name: 'Japan', code: 'JP' },
    { name: 'Spain', code: 'ES' },
    { name: 'United States', code: 'US' }
]);
</script>

Clear Icon

When showClear is enabled, a clear icon is added to reset the CSelect.

vue
<template>
  <CSelect 
      v-model="selectedCity" 
      :options="cities" 
      showClear 
      optionLabel="name" 
      placeholder="Select a City" 
      class="w-full md:w-56" 
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const selectedCity = ref(null);
const cities = ref([
    { name: 'New York', code: 'NY' },
    { name: 'Rome', code: 'RM' },
    { name: 'London', code: 'LDN' },
    { name: 'Istanbul', code: 'IST' },
    { name: 'Paris', code: 'PRS' }
]);
</script>

Loading State

Loading state is enabled with the loading property.

vue
<template>
  <CSelect 
      placeholder="Loading..." 
      loading 
      class="w-full md:w-56" 
  />
</template>

Virtual Scroller

VirtualScroller is used to render a long list of options efficiently like 100K records in this demo. The configuration is done with virtualScrollerOptions property, refer to the VirtualScroller for more information about the available options as it is used internally by CSelect.

vue
<template>
  <CSelect 
      v-model="selectedItem" 
      :options="items" 
      optionLabel="label" 
      optionValue="value" 
      :virtualScrollerOptions="{ itemSize: 38 }" 
      placeholder="Select Item" 
      class="w-full md:w-56" 
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const selectedItem = ref();
const items = ref(Array.from({ length: 100000 }, (_, i) => ({ label: `Item #${i}`, value: i })));
</script>

Filled

Specify the variant property as filled to display the component with a higher visual emphasis than the default outlined style.

vue
<template>
  <CSelect 
      v-model="selectedCity" 
      variant="filled" 
      :options="cities" 
      optionLabel="name" 
      placeholder="Select a City" 
      class="w-full md:w-56" 
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const selectedCity = ref(null);
const cities = ref([
    { name: 'New York', code: 'NY' },
    { name: 'Rome', code: 'RM' },
    { name: 'London', code: 'LDN' },
    { name: 'Istanbul', code: 'IST' },
    { name: 'Paris', code: 'PRS' }
]);
</script>

Sizes

Select provides small and large sizes as alternatives to the base.

vue
<template>
    <div class="card flex flex-col items-center gap-4">
        <CSelect 
            v-model="value1" 
            :options="cities" 
            optionLabel="name" 
            size="small" 
            placeholder="Small" 
            class="w-full 
            md:w-56" 
        />
        <CSelect 
            v-model="value2" 
            :options="cities" 
            optionLabel="name" 
            placeholder="Normal" 
            class="w-full md:w-56" 
        />
        <CSelect 
            v-model="value3" 
            :options="cities" 
            optionLabel="name" 
            size="large" 
            placeholder="Large" 
            class="w-full md:w-56" 
        />
    </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const value1 = ref(null);
const value2 = ref(null);
const value3 = ref(null);
const cities = ref([
    { name: 'New York', code: 'NY' },
    { name: 'Rome', code: 'RM' },
    { name: 'London', code: 'LDN' },
    { name: 'Istanbul', code: 'IST' },
    { name: 'Paris', code: 'PRS' }
]);
</script>

Invalid

Invalid state is displayed using the invalid prop to indicate a failed validation. You can use this style when integrating with form validation libraries.

vue
<template>
  <CSelect 
      v-model="selectedCity" 
      :options="cities" 
      optionLabel="name" 
      placeholder="Select a City" 
      :invalid="!selectedCity" 
      class="w-full md:w-56" 
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';

const selectedCity = ref(null);
const cities = ref([
    { name: 'New York', code: 'NY' },
    { name: 'Rome', code: 'RM' },
    { name: 'London', code: 'LDN' },
    { name: 'Istanbul', code: 'IST' },
    { name: 'Paris', code: 'PRS' }
]);
</script>

Disabled

When disabled is present, the element cannot be edited and focused.

vue
<template>
  <CSelect 
      disabled 
      placeholder="Select a City" 
      class="w-full md:w-56" 
  />
</template>