Select
Select component provides a flexible single-select dropdown with support for synchronous or asynchronous items, search filtering, chip display, images, and virtual scrolling.
Basic usage
Provide an array of items and bind the selected value via v-model. Use value_key and text_key to map fields.
Selected:
<template>
<IkSelect
inline
v-model="countryId"
:items="countries"
value_key="id"
text_key="name"
placeholder="Select country"
/>
<p class="ik-text--sm ik-mt-2">Selected: {{ countryId }}</p>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const countries = [
{ id: 1, name: 'Germany' },
{ id: 2, name: 'France' },
{ id: 3, name: 'Spain' },
];
const countryId = ref();
</script>Filtering
Enable the search input inside the control using filter. For static arrays the filtering is performed locally.
<template>
<IkSelect
inline
v-model="cityId"
:items="cities"
value_key="id"
text_key="name"
filter
placeholder="Search city"
/>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const cities = [
{ id: 1, name: 'Berlin' },
{ id: 2, name: 'Bordeaux' },
{ id: 3, name: 'Barcelona' },
{ id: 4, name: 'Bari' },
{ id: 5, name: 'Brno' },
];
const cityId = ref();
</script>Async loading
Pass a loader function to items to fetch items asynchronously. Use items_per_page for paging and built-in "load more" handling. When async, typing in filter triggers reloading with search_string.
<template>
<IkSelect
inline
v-model="userId"
:items="loadUsers"
value_key="id"
unique_key="id"
text_key="name"
filter
:items_per_page="10"
placeholder="Search users"
/>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const userId = ref();
async function loadUsers({ offset = 0, limit = 10, search_string = '' } = {}) {
// Simulated API
const all = Array.from({ length: 57 }).map((_, i) => ({
id: i + 1,
name: `User ${i + 1}`,
})).filter(u => u.name.toLowerCase().includes(search_string.toLowerCase()));
const items = all.slice(offset, offset + limit);
const has_more = offset + limit < all.length;
return { items, offset, has_more };
}
</script>Chip variant
Use variant_chip to render a compact chip inside the control when an item is selected. You can make the selection clearable with clearable.
<template>
<IkSelect
inline
v-model="tagId"
:items="tags"
value_key="id"
text_key="label"
variant_chip
clearable
placeholder="Pick a tag"
/>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const tags = [
{ id: 1, label: 'Design' },
{ id: 2, label: 'Frontend' },
{ id: 3, label: 'Backend' },
];
const tagId = ref();
</script>Images and subtext
Supply img_key and/or subtext_key (or expressions) to display avatars and secondary text.
<template>
<IkSelect
inline
v-model="memberId"
:items="members"
value_key="id"
text_key="name"
subtext_key="role"
img_key="avatar"
unique_key="id"
filter
placeholder="Select member"
/>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const members = [
{ id: 1, name: 'Alice', role: 'Designer', avatar: 'https://i.pravatar.cc/24?img=1' },
{ id: 2, name: 'Bob', role: 'Engineer', avatar: 'https://i.pravatar.cc/24?img=2' },
{ id: 3, name: 'Carol', role: 'PM', avatar: 'https://i.pravatar.cc/24?img=3' },
];
const memberId = ref();
</script>Variants and sizes
Control appearance with variant and size.
<template>
<div>
<IkSelect
v-model="v1"
:items="opts"
value_key="id"
text_key="name"
unique_key="id"
variant="flat"
size="sm"
placeholder="Flat sm"
class="ik-mb-4"
/>
<IkSelect
v-model="v2"
:items="opts"
value_key="id"
text_key="name"
unique_key="id"
variant="outline"
size="md"
placeholder="Outline md"
class="ik-mb-4"
/>
<IkSelect
v-model="v3"
:items="opts"
value_key="id"
text_key="name"
unique_key="id"
variant="filled"
size="lg"
placeholder="Filled lg"
class="ik-mb-4"
/>
</div>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const opts = [
{ id: 1, name: 'One' },
{ id: 2, name: 'Two' },
{ id: 3, name: 'Three' },
];
const v1 = ref();
const v2 = ref();
const v3 = ref();
</script>Disabled items and control
Disable the whole control with disabled, or pass a predicate via disabled_items to disable specific options.
<template>
<div>
<IkSelect
inline
v-model="valA"
:items="list"
value_key="id"
text_key="label"
unique_key="id"
:disabled_items="isEven"
placeholder="Even disabled"
class="ik-mr-4"
/>
<IkSelect
inline
v-model="valB"
:items="list"
value_key="id"
text_key="label"
unique_key="id"
disabled
placeholder="Disabled control"
/>
</div>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { IkFlex } from '@ikol/ui-kit/components/IkFlex';
import { ref } from 'vue';
const list = [
{ id: 1, label: 'Item 1' },
{ id: 2, label: 'Item 2' },
{ id: 3, label: 'Item 3' },
{ id: 4, label: 'Item 4' },
];
const valA = ref();
const valB = ref();
const isEven = (item) => item.id % 2 === 0;
</script>Slots
IkSelect provides several slots for customizing different parts of the component.
Custom activator
Use the activator slot to completely customize the trigger element.
<template>
<IkSelect
inline
v-model="userId"
:items="users"
value_key="id"
text_key="name"
unique_key="id"
filter
placeholder="Search users"
>
<template #activator="{ on, selected }">
<span style="border: 1px dashed green; padding: 10px; cursor: pointer" v-on="on">
{{ selected ? `Selected: ${selected.name}` : 'Choose user' }}
</span>
</template>
</IkSelect>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Carol' },
];
const userId = ref();
</script>Custom image rendering
Override image rendering with the image slot. This slot is used in the selected display and dropdown items.
<template>
<IkSelect
inline
v-model="memberId"
:items="members"
value_key="id"
text_key="name"
img_key="avatar"
unique_key="id"
filter
placeholder="Select member"
>
<template #image="{ item }">
<div style="width: 24px; height: 24px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); display: flex; align-items: center; justify-content: center; color: white; font-size: 10px; font-weight: bold;">
{{ item.name.charAt(0) }}
</div>
</template>
</IkSelect>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const members = [
{ id: 1, name: 'Alice', avatar: 'https://i.pravatar.cc/24?img=1' },
{ id: 2, name: 'Bob', avatar: 'https://i.pravatar.cc/24?img=2' },
{ id: 3, name: 'Carol', avatar: 'https://i.pravatar.cc/24?img=3' },
];
const memberId = ref();
</script>Custom selected display
Customize how the selected item appears in the control with the selected slot.
<template>
<IkSelect
inline
v-model="countryId"
:items="countries"
value_key="id"
text_key="name"
unique_key="id"
placeholder="Select country"
>
<template #selected="{ item }">
<span style="font-weight: 600;">✓ {{ item.name }}</span>
</template>
</IkSelect>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const countries = [
{ id: 1, name: 'Germany' },
{ id: 2, name: 'France' },
{ id: 3, name: 'Spain' },
];
const countryId = ref();
</script>Custom selected wrapper
For non-chip variants, use the selected-wrapper slot to customize the wrapper element around the selected item display.
<template>
<IkSelect
inline
v-model="tagId"
:items="tags"
value_key="id"
text_key="label"
unique_key="id"
placeholder="Pick a tag"
>
<template #selected-wrapper="{ item }">
<div style="display: flex; align-items: center; gap: 8px; padding: 4px 8px; border: 1px dashed green; border-radius: 4px;">
<span>🏷️</span>
<span>{{ item.label }}</span>
</div>
</template>
</IkSelect>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const tags = [
{ id: 1, label: 'Design' },
{ id: 2, label: 'Frontend' },
{ id: 3, label: 'Backend' },
];
const tagId = ref();
</script>Custom item rendering
Customize how items appear in the dropdown list using the item slot.
<template>
<IkSelect
inline
v-model="userId"
:items="users"
value_key="id"
text_key="name"
unique_key="id"
filter
placeholder="Search users"
>
<template #item="{ item }">
<div style="display: flex; align-items: center; gap: 8px; padding: 8px; border: 1px dashed green; border-radius: 4px; cursor: pointer">
<span>🏷️</span>
<span>{{ item.name }}</span>
</div>
</template>
</IkSelect>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Carol' },
];
const userId = ref();
</script>Custom empty state
Customize the empty state message when no items match using the empty slot. Try filtering items in select:
<template>
<IkSelect
inline
v-model="userId"
:items="users"
value_key="id"
text_key="name"
unique_key="id"
filter
placeholder="Search users"
>
<template #empty>
<div style="text-align: center; padding: 20px; color: #999;">
<div style="font-size: 24px; margin-bottom: 8px;">🔍</div>
<div>No users found</div>
</div>
</template>
</IkSelect>
</template>
<script setup>
import { IkSelect } from '@ikol/ui-kit/components/IkSelect';
import { ref } from 'vue';
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
{ id: 3, name: 'Carol' },
];
const userId = ref();
</script>