Select
KSelect is custom component alternative for native <select>
element.
<KSelect :items="selectItems" />
Props
v-model
Use v-model
for two-way value binding.
Selected service: {{ selectValue || 'none' }}
<KSelect
v-model="selectValue"
:items="selectItems"
/>
items
Prop for providing select item options. Supports grouping items under one group name through providing optional group
property.
interface SelectItem {
label: string
value: string | number
key?: string // optional parameter that will be appended with `-selected` when selected
selected?: boolean
disabled?: boolean
group?: string
}
<KSelect :items="[{
label: 'Service A',
value: 'a',
selected: true,
}, {
label: 'Service B',
value: 'b',
}, {
label: 'Service F',
value: 'f',
disabled: true,
}, {
label: 'Service A1',
value: 'a1',
group: 'Series 1',
}, {
label: 'Service B1',
value: 'b1',
group: 'Series 1',
}, {
label: 'Service A2',
value: 'a2',
group: 'Series 2',
}, {
label: 'Service B2',
value: 'b2',
group: 'Series 2',
}]" />
label
Label associated with the input element.
<KSelect label="Label" :items="selectItems" />
labelAttributes
Label attributes to be passed to underlying KLabel component.
<KSelect :label-attributes="{ info: 'I use the KLabel `info` prop' }" label="Label" :items="selectItems" />
placeholder
Placeholder to be displayed when no item is selected.
<KSelect placeholder="Select service" :items="selectItems" />
clearable
When set to true
, the clear icon will be displayed in front of selected item.
<KSelect clearable :items="selectItems" />
help
Help text to be displayed below the select element.
<KSelect help="Helpful text." :items="selectItems" />
error
When set to true
, error styling will apply.
<KSelect error help="You can use `help` prop for displaying error messages." :items="selectItems" />
width
Use this prop to limit element's width.
<KSelect width="200" :items="selectItems" />
dropdownMaxHeight
Maximum height for dropdown container. Defaults to 300px
.
<KSelect dropdown-max-height="300" :items="selectItems" />
dropdownFooterText
Text to be displayed at the bottom of the dropdown container. Can also be slotted.
<KSelect dropdown-footer-text="Helpful text in the dropdown." :items="selectItems" />
dropdownFooterTextPosition
Defaults to sticky
, but also accepts static
value should you want text passed through dropdownFooterText
prop to be displayed at the bottom of dropdown container after all items.
<KSelect dropdown-footer-text-position="static" dropdown-footer-text="Helpful text in the dropdown." :items="selectItems" />
enableFiltering
By default, items passed to KSelect are not searchable. When enableFiltering
prop is true, clicking on the select element will turn it into input field. You may filter items by typing in the input which will hide non-matching items.
<KSelect enable-filtering placeholder="Try searching for 'service a'" :items="selectItems" />
filterFunction
A custom function to perform item filtering. Expects an object with query string and items to filter through. To keep track of user input you can listen to @query-change
event.
interface SelectFilterFunctionParams {
query: string
items: SelectItem[]
}
TIP
When using filterFunction
prop in conjunction with enableItemCreation
set to true
you must keep track of added and removed custom items to be able to provide the most up to date items to filterFunction
. To achieve that you want to utilize @item-added
and @item-removed
events.
<template>
<KSelect enable-filtering :filter-function="envFilter" placeholder="Try searching for 'dev' or 'prod'" :items="selectItems">
<template #item-template="{ item }">
{{ item?.label }}
<KBadge v-if="item.env">{{ item.env }}</KBadge>
</template>
</KSelect>
</template>
<script setup lang="ts">
import type { SelectItem, SelectFilterFunctionParams } from '@kong/kongponents'
const selectItems: SelectItem[] = [{
label: 'Service A',
value: 'a',
}, {
label: 'Service B',
value: 'b',
env: 'dev',
}, {
label: 'Service F',
value: 'f',
disabled: true,
}, {
label: 'Service A1',
value: 'a1',
group: 'Series 1',
}, {
label: 'Service B1',
value: 'b1',
group: 'Series 1',
}, {
label: 'Service A2',
value: 'a2',
group: 'Series 2',
env: 'prod',
}, {
label: 'Service B2',
value: 'b2',
group: 'Series 2',
env: 'prod',
}]
const envFilter = (params: SelectFilterFunctionParams) =>
params?.items?.filter((item: SelectItem) =>
item.label?.toLowerCase().includes(params.query?.toLowerCase())
|| item.env?.includes(params.query?.toLowerCase()))
</script>
TIP
Should you need to disable the default filter function while still allowing filtering (for example when you want to handle filtering asynchronously by querying an API), you can provide a function that always returns boolean true
to this prop, like so:
<KSelect
enable-filtering
:filter-function="() => true"
:items="selectItems"
/>
reuseItemTemplate
Reuse the same display format provided via the item-template
slot for the selected item.
<KSelect
:items="selectItems"
reuse-item-template
>
<template #item-template="{ item }">
<KongIcon />
{{ item?.label }}
</template>
</KSelect>
enableItemCreation
When used in conjunction with enableFiltering
set to true
, KSelect will suggest adding a new value when filtering produces no results.
<KSelect enable-item-creation enable-filtering placeholder="Try searching for 'service d'" :items="selectItems" />
loading
Pass true
to display loader instead of items in the dropdown. KSelect's item
prop is reactive to changes by design, so that should you need to perform async item fetching/filtering you can execute that logic within the host app and pass items back to KSelect.
The example below utilizes the @query-change
event to simulate async item fetching behind the scenes.
<template>
<KSelect
v-model="asyncItemsModel"
enable-filtering
:items="asyncItems"
:loading="asyncItemsLoading"
@query-change="onAsyncQueryChange"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { SelectItem } from '@kong/kongponents'
const asyncItems: SelectItem[] = [{
label: 'Service A',
value: 'a',
}, {
label: 'Service B',
value: 'b',
}, {
label: 'Service F',
value: 'f',
disabled: true,
}, ...]
const asyncItemsInitial: SelectItem[] = JSON.parse(JSON.stringify(asyncItems.value))
const asyncItemsModel = ref<string>('')
const asyncItemsQuery = ref<string>('')
const asyncItemsLoading = ref<boolean>(false)
const onAsyncQueryChange = (query: string): void => {
if (asyncItemsQuery.value !== query) {
asyncItemsQuery.value = query
fetchAsyncItems()
}
}
const fetchAsyncItems = (): void => {
asyncItemsLoading.value = true
setTimeout(() => {
// normally we would perform api fetching here
// but for the sake of this example let's just filter items locally with some timeout
const items = JSON.parse(JSON.stringify(asyncItemsInitial))
asyncItems.value = items.filter((item: SelectItem) => item.label?.toLowerCase().includes(asyncItemsQuery.value?.toLowerCase()))
asyncItemsLoading.value = false
}, 2000)
}
</script>
kpopAttributes
Attributes to be passed to underlying KPopover component. See KPopover's props for more info.
HTML Attributes
required
KSelect will display a red dot next to label when required
attribute is passed.
<KSelect
label="Label"
required
:items="selectItems"
/>
disabled
Use this attribute to disable interaction with the element.
<KSelect
label="Disabled"
disabled
:items="selectItems"
/>
Slots
item-template
Use this slot to pass custom content to the items. The slot exposes item
slot prop.
<template>
<KSelect :items="selectItems">
<template #item-template="{ item }">
<div class="custom-item">
<KongIcon />
<div class="custom-item-title-container">
<span class="custom-item-title">{{ item?.label }}</span>
<span class="custom-item-description">{{ item?.label }} description.</span>
</div>
</div>
</template>
</KSelect>
</template>
<style lang="scss" scoped>
.custom-item {
display: flex;
flex-direction: row;
gap: $kui-space-30;
&-title-container {
flex: 1;
}
&-title {
display: block;
}
&-description {
color: $kui-color-text-neutral;
display: block;
font-size: $kui-font-size-20;
}
}
</style>
selected-item-template
Use this slot to provide custom content to the selected item. The slot exposes item
slot prop.
<KSelect :items="selectItems">
<template #selected-item-template="{ item }">
<KongIcon />
{{ item?.label }}
</template>
</KSelect>
dropdown-footer-text
A slot alternative for dropdownFooterText
prop.
<KSelect :items="selectItems">
<template #dropdown-footer-text>
<KongIcon />
Dropdown footer content.
</template>
</KSelect>
loading
Content to be displayed when loading
prop is true
. Note that this prop only applies when enableFiltering
is true
.
<KSelect :loading="loading" enable-filtering :items="selectItems">
<template #loading>
Services loading...
</template>
</KSelect>
empty
Slot to display custom content when items is empty or no items match filter query.
<KSelect :items="[]">
<template #empty>
No services found.
</template>
</KSelect>
label-tooltip
Use this prop to pass any custom content to label tooltip.
<KSelect label="Label" :items="selectItems">
<template #label-tooltip>Id: <code>8576925e-d7e0-4ecd-8f14-15db1765e69a</code></template>
</KSelect>
Events
selected
Event payload is select item.
input and update:modelValue
Event payload is selected item value
.
change
Event payload is select item.
query-change
Event payload is query string.
item-added
Event payload is added item.
item-removed
Event payload is removed item.