Demos
How to import
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
</script>
Write the options as <Select.Option> and <Select.OptGroup>, or use the named exports SelectOption and SelectOptGroup.
Basic Usage
Each Option tag must declare the value attribute, and the default slot content of the Option, or its label, will be rendered to the drop-down list
Code
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
</script>
<template>
<Select aria-label="业务线" defaultValue="douyin" style="width: 120px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option disabled value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
<br />
<br />
<Select aria-label="业务线" defaultValue="douyin" disabled style="width: 120px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
</Select>
<br />
<br />
<Select aria-label="业务线" placeholder="请选择业务线" style="width: 120px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option disabled value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
</template>Pass Option as an array
You can pass an array of objects directly through optionList. Each object must contain the value / label attribute.
label accepts a string or a number; content with markup goes in the default slot of Select.Option.
Code
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
const list = [
{ value: 'douyin', label: '抖音', otherKey: 0 },
{ value: 'ulikecam', label: '轻颜相机', disabled: true, otherKey: 1 },
{ value: 'jianying', label: '剪映', otherKey: 2 },
{ value: 'toutiao', label: '今日头条', otherKey: 3 },
];
</script>
<template>
<Select aria-label="业务线" :optionList="list" placeholder="请选择业务线" style="width: 180px" />
</template>Multi-choice
Since v2.28, the selector will have its own maxHeight 270, and the content can be viewed by scrolling vertically after it exceeds.
Configuration multiple properties that can support multi-selection
Configuration maxTagCount. You can limit the number of options displayed, and the excess will be displayed in the form of + N
Configure ellipsisTrigger (>= v2.28.0) to do adaptive processing on the overflow part of the tag. When the width is insufficient, the last tag content will be truncated. After enabling this function, there will be a certain performance loss, and it is not recommended to use it in large form scenarios
Configure expandRestTagsOnClick (>= v2.28.0) to display all remaining tags by clicking when maxTagCount is set
Use showRestTagsPopover (>= v2.22.0) to set whether hover +N displays Popover after exceeding maxTagCount, the default is false. Also, popovers can be configured in the restTagsPopoverProps property
Configuration max Properties can limit the maximum number of options and cannot be selected beyond the maximum limit, while emitting the exceed event
Code
<script setup lang="ts">
import { Select, Toast } from '@fibrous/semi-ui-vue';
const onExceed = () => Toast.warning('最多只允许选择两项');
</script>
<template>
<Select aria-label="Select 示例" :defaultValue="['douyin', 'ulikecam']" multiple style="width: 320px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
<br />
<br />
<Select aria-label="Select 示例" :defaultValue="['douyin', 'ulikecam', 'jianying']" :maxTagCount="2" multiple :restTagsPopoverProps="{ position: 'top' }" showRestTagsPopover style="width: 320px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
<br />
<br />
<Select aria-label="Select 示例" :defaultValue="['douyin']" :max="2" multiple style="width: 320px" @exceed="onExceed">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
<br />
<br />
<Select aria-label="Select 示例" :defaultValue="['xigua', 'ulikecam', 'jianying', 'douyin']" ellipsisTrigger expandRestTagsOnClick :maxTagCount="2" multiple :restTagsPopoverProps="{ position: 'top' }" showRestTagsPopover style="width: 220px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
</template>With Group
Grouping Option with Select.OptGroup (only supports declaring the options in the default slot, and does not support pass in through optionList). Use the label prop for the group title, or the #label slot for a title with markup
Code
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
</script>
<template>
<Select aria-label="地区" filter placeholder="" style="width: 180px">
<Select.OptGroup label="Asia">
<Select.Option value="a-1">China</Select.Option>
<Select.Option value="a-2">Korea</Select.Option>
</Select.OptGroup>
<Select.OptGroup label="Europe">
<Select.Option value="b-1">Germany</Select.Option>
<Select.Option value="b-2">France</Select.Option>
</Select.OptGroup>
<Select.OptGroup label="South America">
<Select.Option value="c-1">Peru</Select.Option>
</Select.OptGroup>
</Select>
</template>Code
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
const data = [
{
label: 'Asia',
children: [
{ value: 'a-1', label: 'China' },
{ value: 'a-2', label: 'Korea' },
],
},
{
label: 'Europe',
children: [
{ value: 'b-1', label: 'Germany' },
{ value: 'b-2', label: 'France' },
],
},
{
label: 'South America',
children: [{ value: 'c-1', label: 'Peru' }],
},
];
</script>
<template>
<Select aria-label="地区" filter placeholder="" style="width: 180px">
<Select.OptGroup v-for="group in data" :key="group.label" :label="group.label">
<Select.Option v-for="option in group.children" :key="option.value" :label="option.label" :value="option.value" />
</Select.OptGroup>
</Select>
</template>Different sizes
Size: small / default / large
Code
<script setup lang="ts">
import { Select, SelectOption } from '@fibrous/semi-ui-vue';
</script>
<template>
<Select aria-label="small" placeholder="请选择业务线" size="small" :style="{ width: '180px' }">
<SelectOption value="ulikecam">轻颜相机</SelectOption>
</Select>
<br />
<br />
<Select aria-label="default" placeholder="请选择业务线" :style="{ width: '180px' }">
<SelectOption value="ulikecam">轻颜相机</SelectOption>
</Select>
<br />
<br />
<Select aria-label="large" placeholder="请选择业务线" size="large" :style="{ width: '180px' }">
<SelectOption value="ulikecam">轻颜相机</SelectOption>
</Select>
</template>Different validate status
validateStatus: default / warning / error
Code
<script setup lang="ts">
import { Select, SelectOption } from '@fibrous/semi-ui-vue';
</script>
<template>
<Select aria-label="default" :style="{ width: '180px' }">
<SelectOption value="ulikecam">轻颜相机</SelectOption>
</Select>
<br />
<br />
<Select aria-label="warning" :style="{ width: '180px' }" validateStatus="warning">
<SelectOption value="ulikecam">轻颜相机</SelectOption>
</Select>
<br />
<br />
<Select aria-label="error" :style="{ width: '180px' }" validateStatus="error">
<SelectOption value="ulikecam">轻颜相机</SelectOption>
</Select>
</template>Configure Prefix, Suffix, Clear Button
- You can pass the selection box prefix through the
#prefixslot, the selection box suffix through the#suffixslot, for text or nodes
The left and right padding is automatically brought when the slot content is text or Icon. If it is a custom node, the left and right padding is 0.
- Whether to show the clear button is displayed by
showClear - Whether to show the right drop-down arrow is displayed by
showArrow
Code
<script setup lang="ts">
import { IconGift, IconVigoLogo } from '@fibrous/semi-icons-vue';
import { Select } from '@fibrous/semi-ui-vue';
</script>
<template>
<Select aria-label="Select 示例" defaultValue="ulikecam" showClear style="width: 320px">
<template #prefix>
<IconVigoLogo />
</template>
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
<br />
<br />
<Select aria-label="Select 示例" defaultValue="ulikecam" :showArrow="false" style="width: 320px">
<template #prefix>
<IconVigoLogo />
</template>
<template #suffix>
<IconGift />
</template>
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
</template>Additional items
We have reserved two slots at the bottom of the pop-up layer, which you can use when you need to add a custom node to the pop-up layer.
UseinnerTopSlot or outerTopSlot to pass the custom node, which will be rendered at the top of the pop-up layer. UseinnerBottomSlot or outerBottomSlot instead at the bottom.
In Vue they are named slots of the same names: #innerBottomSlot, #outerBottomSlot, #innerTopSlot and #outerTopSlot.
innerTopSlotandinnerBottomSlotwill be rendered inside the Option ListouterTopSlotandouterBottomSlotwill be rendered to level with the option List
outerBottomSlot:
innerBottomSlot:
Code
<script setup lang="ts">
import { Select, SelectOption } from '@fibrous/semi-ui-vue';
const innerSlotStyle = {
backgroundColor: 'var(--color-white)',
height: '36px',
display: 'flex',
alignItems: 'center',
cursor: 'pointer',
paddingLeft: '32px',
borderTop: '1px solid var(--semi-color-border)',
borderRadius: '0 0 6px 6px',
color: 'var(--semi-color-link)',
};
const outSlotStyle = {
backgroundColor: 'var(--semi-color-fill-0)',
height: '36px',
display: 'flex',
paddingLeft: '32px',
color: 'var(--semi-color-link)',
alignItems: 'center',
cursor: 'pointer',
borderTop: '1px solid var(--semi-color-border)',
borderRadius: '0 0 6px 6px',
};
</script>
<template>
<div>
<p>outerBottomSlot:</p>
<Select aria-label="outerBottomSlot" :autoAdjustOverflow="false" defaultOpen :dropdownStyle="{ width: '180px' }" :maxHeight="150" placeholder="自定义外侧底部slot,始终显示" position="bottom" :style="{ width: '300px' }">
<SelectOption value="douyin">抖音</SelectOption>
<SelectOption value="ulikecam">轻颜相机</SelectOption>
<SelectOption value="jianying">剪映</SelectOption>
<SelectOption value="duoshan">多闪</SelectOption>
<SelectOption value="xigua">西瓜视频</SelectOption>
<template #outerBottomSlot>
<div :style="outSlotStyle">
<span :style="{ color: 'var(--semi-color-link)' }">未找到应用?</span>
</div>
</template>
</Select>
<p :style="{ marginTop: '200px' }">innerBottomSlot:</p>
<Select aria-label="innerBottomSlot" :dropdownStyle="{ width: '180px' }" :maxHeight="150" placeholder="自定义内侧底部slot,滚动至底部显示" :style="{ width: '300px' }">
<SelectOption value="douyin">抖音</SelectOption>
<SelectOption value="ulikecam">轻颜相机</SelectOption>
<SelectOption value="jianying">剪映</SelectOption>
<SelectOption value="duoshan">多闪</SelectOption>
<SelectOption value="xigua">西瓜视频</SelectOption>
<template #innerBottomSlot>
<div :style="innerSlotStyle">点击加载更多</div>
</template>
</Select>
</div>
</template>Using outerTopSlot to insert content
Code
<script setup lang="ts">
import { ref } from 'vue';
import { RadioGroup, Select, type RadioChangeEvent } from '@fibrous/semi-ui-vue';
interface Item {
value: string;
label: string;
}
const list: Record<string, Item[]> = {
component: [
{ value: 'select', label: '选择器' },
{ value: 'tabs', label: '标签' },
{ value: 'avatar', label: '头像' },
{ value: 'button', label: '按钮' },
],
design: [
{ value: 'color', label: '颜色' },
{ value: 'dark', label: '暗色模式' },
{ value: 'icon', label: '图标' },
{ value: 'font', label: '字体' },
],
feedback: [
{ value: 'faq', label: '常见问题' },
{ value: 'join', label: '加入用户群' },
{ value: 'hornbill', label: '犀鸟反馈问题' },
],
};
const categoryOptions = [
{ value: 'component', label: '组件' },
{ value: 'design', label: '设计' },
{ value: 'feedback', label: '反馈' },
];
const categoryWrapper = {
padding: '8px 12px',
borderBottom: '0.5px solid var(--semi-color-border)',
};
const key = ref('component');
const value = ref<Item | undefined>({ value: 'faq', label: '常见问题' });
const changeCategory = (event: RadioChangeEvent) => {
key.value = String(event.target.value);
};
</script>
<template>
<Select v-model="value" aria-label="选项" :autoAdjustOverflow="false" changeWithObject defaultOpen :optionList="list[key]" :style="{ width: '200px' }">
<template #outerTopSlot>
<!-- The radio group switches with arrow keys, so categories need no tabpanel association -->
<div :style="categoryWrapper">
<RadioGroup aria-label="选项分类" buttonSize="small" :modelValue="key" :options="categoryOptions" type="button" @change="changeCategory" />
</div>
</template>
</Select>
</template>Controlled component
Once bound with v-model (that is, modelValue), Select is a controlled component, and the value selected is entirely determined by it. A modelValue of undefined is treated as uncontrolled.
Code
<script setup lang="ts">
import { ref } from 'vue';
import { Select } from '@fibrous/semi-ui-vue';
const value = ref<string | undefined>('xigua');
</script>
<template>
<Select v-model="value" aria-label="业务线" placeholder="受控的Select" style="width: 300px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
</template>Dynamic Modification Options
If you need to update Options dynamically, you should use a controlled modelValue
Code
<script setup lang="ts">
import { ref } from 'vue';
import { Button, Select } from '@fibrous/semi-ui-vue';
const options = ref([1, 2, 3, 4]);
function add() {
const length = Math.ceil(Math.random() * 10);
options.value = Array.from({ length }, (_, i) => i + 1);
}
</script>
<template>
<Select aria-label="数字" :modelValue="4" placeholder="请选择" style="width: 180px">
<Select.Option v-for="option in options" :key="option" :value="option">{{ option }}</Select.Option>
</Select>
<br />
<br />
<Button @click="add">changeOptions Dynamic</Button>
</template>Linkage Select
Use a controlled modelValue to link different Selects. If it is a complex linkage with a hierarchical relationship, it is recommended to use Cascader components directly
Code
<script setup lang="ts">
import { computed, ref } from 'vue';
import { Select } from '@fibrous/semi-ui-vue';
const provinces = ['四川', '广东'];
const maps: Record<string, string[]> = {
四川: ['成都', '都江堰'],
广东: ['广州', '深圳', '东莞'],
};
const province = ref(provinces[0]);
const cities = computed(() => maps[province.value]);
const city = ref<string | undefined>(cities.value[0]);
function changeProvince(newProvince?: string) {
if (!newProvince) {
return;
}
province.value = newProvince;
city.value = maps[newProvince][0];
}
</script>
<template>
<Select aria-label="省份" :modelValue="province" style="width: 150px; margin: 10px" @change="changeProvince">
<Select.Option v-for="item in provinces" :key="item" :value="item">{{ item }}</Select.Option>
</Select>
<Select v-model="city" aria-label="城市" style="width: 150px; margin: 10px">
<Select.Option v-for="item in cities" :key="item" :value="item">{{ item }}</Select.Option>
</Select>
</template>Search
You can turn on the search capability by setting filter to true.
The default search strategy will include comparison of the input value with the label value of option
By default, the search keywords will be cleared automatically after multiple selection is selected. If you want to keep it, you can turn off the default behavior by setting autoClearSearchValue to false (provided after v2.3)
Code
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
</script>
<template>
<Select aria-label="单选" filter placeholder="带搜索功能的单选" style="width: 180px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
<br />
<br />
<Select aria-label="多选" :autoClearSearchValue="false" filter multiple placeholder="带搜索功能的多选" style="width: 300px">
<Select.Option value="semi-0">Semi-0</Select.Option>
<Select.Option value="semi-1">Semi-1</Select.Option>
<Select.Option value="semi-2">Semi-2</Select.Option>
<Select.Option value="semi-3">Semi-3</Select.Option>
<Select.Option value="semi-4">Semi-4</Select.Option>
</Select>
</template>Search position
The default search input is displayed on the Select Trigger. You can specify different positions through searchPosition, and you can choose dropdown or trigger. Available after v2.61.0
If you want to customize the placeholder of the Input search box in the dropdown, you can control it through searchPlaceholder
If the searchPosition is trigger, when showClear=true, clicking the clear button of the input will clear the selected items and the search text in the input at the same time
If the searchPosition is dropdown, when showClear=true, clicking the clear button of the trigger will clear the selected items, clicking the clear button in the dropdown input will clear search text
Code
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
</script>
<template>
<Select aria-label="单选" defaultValue="ulikecam" filter placeholder="我的搜索框在下拉菜单中" searchPlaceholder="带搜索功能的单选" searchPosition="dropdown" style="width: 200px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
<br />
<br />
<Select aria-label="多选" :autoClearSearchValue="false" :defaultValue="['semi-1']" filter multiple placeholder="我的搜索框在下拉菜单中" searchPlaceholder="带搜索功能的多选" searchPosition="dropdown" style="width: 300px">
<Select.Option value="semi-0">Semi-0</Select.Option>
<Select.Option value="semi-1">Semi-1</Select.Option>
<Select.Option value="semi-2">Semi-2</Select.Option>
<Select.Option value="semi-3">Semi-3</Select.Option>
<Select.Option value="semi-4">Semi-4</Select.Option>
</Select>
</template>Remote search
A multi-select example with remote search, request debounce, loading status.
- Use
filterturn on the search capability. - Use
remoteto disabled local filter - Dynamic Update
optionListafteronSearchcallback - Update
loadingwhen fetching data / finish
- Use a controlled
modelValue, and get the keyword from the@searchevent
Code
<script setup lang="ts">
import { ref } from 'vue';
import { debounce } from 'es-toolkit';
import { Select } from '@fibrous/semi-ui-vue';
interface Item {
value: string;
label: string;
type: number;
}
const mockSearch = (inputValue: string): Item[] => {
const length = Math.ceil(Math.random() * 100);
return Array.from({ length }, (_v, i) => {
return { value: inputValue + i, label: `相近业务 ${inputValue}${i}`, type: i + 1 };
});
};
const loading = ref(false);
const list = ref<Item[]>([
{ value: 'douyin', label: '抖音', type: 1 },
{ value: 'xingtu', label: '醒图', type: 2 },
{ value: 'jianying', label: '剪映', type: 3 },
{ value: 'toutiao', label: '今日头条', type: 4 },
]);
const value = ref<Item[]>([]);
const handleSearch = debounce((inputValue: string) => {
loading.value = true;
if (inputValue) {
const result = mockSearch(inputValue);
setTimeout(() => {
loading.value = false;
list.value = result;
}, 1000);
} else {
loading.value = false;
}
}, 1000);
</script>
<template>
<Select v-model="value" aria-label="远程搜索" changeWithObject filter :loading="loading" multiple :optionList="list" remote style="width: 300px" @search="handleSearch">
<template #emptyContent />
</Select>
</template>Custom search strategy
By default, the user's search input will be compared with the option's label value as a string include.
You can set filter as a custom function to customize your filter strategy.
Code
<script setup lang="ts">
import { Select, type SelectOptionProps } from '@fibrous/semi-ui-vue';
function searchLabel(sugInput: string, option: SelectOptionProps) {
const label = String(option.label).toUpperCase();
const sug = sugInput.toUpperCase();
return label.includes(sug);
}
</script>
<template>
<Select aria-label="业务线" :filter="searchLabel" placeholder="try douyin" style="width: 180px">
<Select.Option value="douyin">douyin</Select.Option>
<Select.Option value="ulikecam">HOTSOON</Select.Option>
<Select.Option value="jianying">PIPIXIA</Select.Option>
<Select.Option value="xigua">XIGUA</Select.Option>
</Select>
</template>Custom selection rendering
By default, the label of the option, or the content of its default slot, will be backfilled into the selection box when the option is selected.
But you can customize the rendering of the selection box through scoped slots, whose parameters are { option, index, disabled, onClose }
#selectedItem: in a single Select it replaces the content shown in the selection box; in a multiple Select it replaces only the content inside the built-in tag, which keeps its background color and close button#tag: in a multiple Select it replaces the whole tag, and takes precedence over#selectedItemwhen both are given- Call
onCloseto remove the option; in a single Select it clears the value
shenyue@example.comCode
<script setup lang="ts">
import { Avatar, Select, Tag } from '@fibrous/semi-ui-vue';
interface ListItem {
name: string;
email: string;
avatar: string;
}
const list: ListItem[] = [
{
name: '夏可漫',
email: 'xiakeman@example.com',
avatar: '/assets/placeholder/avatar-a.svg',
},
{
name: '申悦',
email: 'shenyue@example.com',
avatar: '/assets/root-web-sites/bag.jpeg',
},
{
name: '曲晨一',
email: 'quchenyi@example.com',
avatar: '/assets/placeholder/avatar-c.svg',
},
{
name: '文嘉茂',
email: 'wenjiamao@example.com',
avatar: '/assets/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png',
},
];
const onChange = (value: unknown) => console.log(value);
const optionStyle = {
display: 'flex',
paddingLeft: '24px',
paddingTop: '10px',
paddingBottom: '10px',
};
</script>
<template>
<Select aria-label="单选" defaultValue="申悦" placeholder="请选择" style="width: 280px; height: 40px" @change="onChange">
<template #selectedItem="{ option }">
<div style="display: flex; align-items: center">
<Avatar alt="" size="small" :src="option.avatar" />
<span style="margin-left: 8px">{{ option.email }}</span>
</div>
</template>
<Select.Option v-for="item in list" :key="item.email" v-bind="item" showTick :style="optionStyle" :value="item.name">
<Avatar alt="" size="small" :src="item.avatar" />
<div style="margin-left: 8px">
<div style="font-size: 14px">{{ item.name }}</div>
<div style="color: var(--color-text-2); font-size: 12px; line-height: 16px; font-weight: normal">
{{ item.email }}
</div>
</div>
</Select.Option>
</Select>
<Select aria-label="多选圆形头像" :defaultValue="['申悦', '曲晨一']" :maxTagCount="2" multiple placeholder="请选择" style="width: 280px; margin-top: 20px" @change="onChange">
<template #tag="{ option, onClose }">
<Tag :avatarSrc="option.avatar" avatarShape="circle" closable size="large" @close="onClose">
{{ option.name }}
</Tag>
</template>
<Select.Option v-for="item in list" :key="item.email" v-bind="item" showTick :style="optionStyle" :value="item.name">
<Avatar alt="" size="small" :src="item.avatar" />
<div style="margin-left: 8px">
<div style="font-size: 14px">{{ item.name }}</div>
<div style="color: var(--color-text-2); font-size: 12px; line-height: 16px; font-weight: normal">
{{ item.email }}
</div>
</div>
</Select.Option>
</Select>
<Select aria-label="多选方形头像" :defaultValue="['申悦', '曲晨一']" :maxTagCount="2" multiple placeholder="请选择" style="width: 280px; margin-top: 20px" @change="onChange">
<template #tag="{ option, onClose }">
<Tag :avatarSrc="option.avatar" avatarShape="square" closable size="large" @close="onClose">
{{ option.name }}
</Tag>
</template>
<Select.Option v-for="item in list" :key="item.email" v-bind="item" showTick :style="optionStyle" :value="item.name">
<Avatar alt="" size="small" :src="item.avatar" />
<div style="margin-left: 8px">
<div style="font-size: 14px">{{ item.name }}</div>
<div style="color: var(--color-text-2); font-size: 12px; line-height: 16px; font-weight: normal">
{{ item.email }}
</div>
</div>
</Select.Option>
</Select>
</template>Custom pop-up layer style
You can control the style of the pop-up layer through dropdownClassName, dropdownStyle
For example, when you customize the width of the pop-up layer, you can pass the width through drowndownStyle
Code
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
const dropdownStyle = { width: '250px' };
</script>
<template>
<Select aria-label="业务线" :dropdownStyle="dropdownStyle" dropdownClassName="test" placeholder="自定义弹出层样式的" style="width: 180px">
<Select.Option value="douyin">抖音</Select.Option>
<Select.Option value="ulikecam">轻颜相机</Select.Option>
<Select.Option value="jianying">剪映</Select.Option>
<Select.Option value="xigua">西瓜视频</Select.Option>
</Select>
</template>Get all attribute of selected option
By default, the change event only gives you the value of the selected option.
If you need to take other attributes of the selected option, you can use the changeWithObject property (a boolean property, not an event)
At this time, the payload of change and update:modelValue will be an object containing various attributes of the selected option, eg: { value, label, ...rest }
onChange回调:
onChange回调:
Code
<script setup lang="ts">
import { ref } from 'vue';
import { Select, TextArea } from '@fibrous/semi-ui-vue';
interface Item {
value: string;
label: string;
type: number;
}
const list: Item[] = [
{ value: 'douyin', label: '抖音', type: 1 },
{ value: 'ulikecam', label: '轻颜相机', type: 2 },
{ value: 'jianying', label: '剪映', type: 3 },
{ value: 'toutiao', label: '今日头条', type: 4 },
];
const cbValue = ref<Item>();
const multipleCbValue = ref<Item[]>();
// Select infers its value type from the value, not from optionList, so an empty typed default gives change Item[]
const noItems: Item[] = [];
const onChange = (value?: Item) => {
cbValue.value = value;
console.log(value);
};
const onMultipleChange = (value: Item[]) => {
multipleCbValue.value = value;
console.log(value);
};
</script>
<template>
<div>
<div>
<Select aria-label="单选" changeWithObject :defaultValue="list[0]" :optionList="list" placeholder="单选" style="width: 150px" @change="onChange" />
<h4 id="select-on-change-with-object-single">onChange回调:</h4>
<TextArea aria-labelledby="select-on-change-with-object-single" autosize :modelValue="JSON.stringify(cbValue)" :rows="2" style="width: 320px; margin-bottom: 48px" />
</div>
<div>
<Select aria-label="多选" changeWithObject :defaultValue="noItems" multiple :optionList="list" placeholder="多选" style="width: 320px" @change="onMultipleChange" />
<h4 id="select-on-change-with-object-multiple">onChange回调:</h4>
<TextArea aria-labelledby="select-on-change-with-object-multiple" autosize :modelValue="JSON.stringify(multipleCbValue)" style="width: 320px" />
</div>
</div>
</template>Create entries
You can create and select entries that do not exist in the options by setting allowCreate=true
You can customize the content display when creating the label through the #createItem="{ inputValue, focus, style }" scoped slot (note that you need to customize the style, and with virtualization you must apply style to the custom element). Without it the locale text for "Create" followed by the input is shown. The create event fires when an option is created
In addition, can be used with the defaultActiveFirstOption property to automatically select the first item. When you enter directly and press Enter, you can immediately create an Option
Code
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
const optionList = [
{ value: 'douyin', label: '抖音' },
{ value: 'ulikecam', label: '轻颜相机' },
{ value: 'jianying', label: '剪映' },
{ value: 'toutiao', label: '今日头条' },
];
</script>
<template>
<Select allowCreate aria-label="业务线" defaultActiveFirstOption filter multiple :optionList="optionList" style="width: 400px" @change="(value) => console.log(value)" />
<br />
<br />
<Select allowCreate aria-label="业务线" defaultActiveFirstOption filter multiple :optionList="optionList" placeholder="With renderCreateItem" style="width: 400px" @change="(value) => console.log(value)">
<template #createItem="{ inputValue, style }">
<div :style="[{ padding: '10px' }, style]">Create Item:{{ inputValue }}</div>
</template>
</Select>
</template>Virtualize
Turn on list virtualization when passing in virtualize to optimize performance when there are a large number of Option nodes virtualize is an object containing the following values:
- height: Option list height value, default 270 (before v2.20.8 was 300)
- width: Option list width value, default 100%
- itemSize: The height of each line of Option, must be passed
Code
<script setup lang="ts">
import { Select } from '@fibrous/semi-ui-vue';
const options = Array.from({ length: 3000 }, (_, i) => ({ label: `option-${i}`, value: i }));
const virtualize = {
height: 270,
width: '100%',
itemSize: 36,
};
</script>
<template>
<Select aria-label="virtualize" filter :optionList="options" placeholder="拥有3k个Option的Select" :style="{ width: '260px' }" :virtualize="virtualize" />
</template>Custom Trigger
If the default layout style of the selection box does not meet your needs, you can use the #trigger scoped slot to customize the content of the selection box
If you want to keep the search and filter ability without rendering the Input structure yourself, you can also set searchPosition='dropdown' to put the default search box in the dropdown list
The parameters of #trigger are as follows
interface SelectTriggerSlotProps {
value: SelectOptionProps[]; // All currently selected options
inputValue: string; // The current search keyword
placeholder?: string; // Select placeholder
disabled: boolean; // Whether to disable Select
componentProps: Record<string, unknown>; // All props passed to Select by users
onSearch: (inputValue: string) => void; // Updates the search keyword. Call it when the value of your custom Input changes, to synchronize the state to the Select internal. filter needs to be set too
onClear: (event?: MouseEvent) => void; // Clears the selection. When bound to a control inside the trigger, pass the click event so that click does not reopen the dropdown
onRemove: (option: SelectOptionProps) => void; // Removes a single selected option, which needs at least label and value
}
不同背景色的触发器
使用 circle Tag 作为触发器
Code
<script setup lang="ts">
import { ref } from 'vue';
import { IconAppCenter, IconChevronDown } from '@fibrous/semi-icons-vue';
import { Select, Tag } from '@fibrous/semi-ui-vue';
const valList = ref(['douyin', 'ulikecam']);
const list = [
{ value: 'douyin', label: '抖音' },
{ value: 'ulikecam', label: '轻颜相机' },
{ value: 'jianying', label: '剪映' },
{ value: 'toutiao', label: '今日头条' },
];
</script>
<template>
<div>
<h4>不同背景色的触发器</h4>
<Select v-model="valList" aria-label="不同背景色的触发器" filter multiple :optionList="list" searchPosition="dropdown" :style="{ width: '240px' }">
<template #trigger="{ value }">
<div
:style="{
minWidth: '112px',
backgroundColor: 'var(--semi-color-primary-light-default)',
height: '32px',
display: 'flex',
alignItems: 'center',
paddingLeft: '12px',
borderRadius: '3px',
color: 'var(--semi-color-primary)',
}"
>
<div :style="{ fontWeight: 600, flexShrink: 0, fontSize: '14px' }">业务线</div>
<div
:style="{
margin: '4px',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
flexGrow: 1,
overflow: 'hidden',
}"
>
{{ value.map((item) => item.label).join(' , ') }}
</div>
<IconAppCenter :style="{ marginRight: '8px', flexShrink: 0 }" />
</div>
</template>
</Select>
<br />
<br />
<h4>使用 circle Tag 作为触发器</h4>
<Select v-model="valList" aria-label="circle Tag 触发器" filter multiple :optionList="list" searchPosition="dropdown" :style="{ width: '240px', marginTop: '20px', outline: 0 }">
<template #trigger="{ value }">
<div
:style="{
margin: '4px',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
flexGrow: 1,
overflow: 'hidden',
display: 'flex',
alignItems: 'center',
}"
>
<Tag color="cyan" shape="circle" size="large">
{{ value.map((item) => item.label).join(' / ') }}
<template #suffixIcon>
<IconChevronDown />
</template>
</Tag>
</div>
</template>
</Select>
</div>
</template>The following is a more complex example: Reusing the drag-and-sort capability of TagInput and adding sorting to Select through a custom trigger.
可对已选项拖拽重新排序的 Select
douyin,ulikecam
Code
<script setup lang="ts">
import { ref } from 'vue';
import { Select, TagInput } from '@fibrous/semi-ui-vue';
const valList = ref(['douyin', 'ulikecam']);
const inputVal = ref('');
const list = [
{ value: 'douyin', label: '抖音' },
{ value: 'ulikecam', label: '轻颜相机' },
{ value: 'jianying', label: '剪映' },
{ value: 'toutiao', label: '今日头条' },
];
const handleSort = (currentLabels: string[]) => {
valList.value = currentLabels.flatMap((item) => list.find((i) => i.label === item)?.value ?? []);
};
</script>
<template>
<h4>可对已选项拖拽重新排序的 Select</h4>
<Select v-model="valList" aria-label="可拖拽排序的 Select" filter multiple :optionList="list" :style="{ width: '240px' }">
<template #trigger="{ value, onSearch }">
<div role="presentation" @keydown.stop>
<TagInput
:allowDuplicates="false"
draggable
:inputValue="inputVal"
:modelValue="value.map((item) => String(item.label))"
showClear
@change="handleSort"
@inputChange="
(word) => {
onSearch(word);
inputVal = word;
}
"
/>
</div>
</template>
</Select>
</template>Custom Option Render
- Simple customization: Put content with markup in the default slot of
Select.Option, you can control the rendering of the candidates, and the content will automatically bring styles such as padding, background color, etc. - Complete customization: Through the
#optionItemscoped slot, you can completely take over the rendering of the candidates in the list, and get the relevant state values from the slot parameters. Achieve a higher degree of freedom of structural rendering
The parameters are{ id, value, label, selected, focused, disabled, inputValue, class, style, onClick, onMouseenter }. Notice:- The
stylein the parameters needs to be consumed on wrapper dom, otherwise it will not be able to be used normally in virtualization scenarios - The
classandonMouseenterin the parameters need to be bound on the wrapper dom, otherwise the display will be problematic when the upper and lower keyboards are operated - The styles of selected, focused, disabled, etc. state need to be added by yourself, and you can get the relative boolean value from the parameters
- Bind the
onClickin the parameters to the wrapper dom so that a click selects the option - Put the
idin the parameters on the wrapper dom withrole="option",aria-selectedandaria-disabled: the Select pointsaria-activedescendantat that id, so screen readers announce the option reached with the arrow keys; Select also uses this id to scroll the option into view when the dropdown opens or the arrow keys move
- The
Code
<script setup lang="ts">
import { ref } from 'vue';
import { Checkbox, Highlight, Select } from '@fibrous/semi-ui-vue';
const inputValue = ref('');
const optionList = [
{ value: 'douyin', label: '抖音', otherKey: 0 },
{ value: 'ulikecam', label: '轻颜相机', disabled: true, otherKey: 1 },
{ value: 'jianying', label: '剪映', otherKey: 2 },
{ value: 'toutiao', label: '今日头条', otherKey: 3 },
];
</script>
<template>
<Select aria-label="单选" dropdownClassName="components-select-demo-renderOptionItem" filter :optionList="optionList" placeholder="单选" style="width: 180px" @search="inputValue = $event">
<!--
Put style on the outer DOM or the virtual list breaks; add selected/focused/disabled styles from the slot
params; bind onMouseenter and class on the outer DOM or arrow keys display wrongly; put id there so screen
readers announce the option the arrow keys reach
-->
<template #optionItem="{ id, disabled, selected, label, focused, class: className, style, onClick, onMouseenter }">
<div
:id="id"
:aria-disabled="disabled"
:aria-selected="selected"
:class="[
'custom-option-render',
{
'custom-option-render-focused': focused,
'custom-option-render-disabled': disabled,
'custom-option-render-selected': selected,
},
className,
]"
role="option"
:style="style"
@click="onClick"
@mouseenter="onMouseenter"
>
<Checkbox :modelValue="selected" />
<div class="option-right">
<Highlight :searchWords="[inputValue]" :sourceString="String(label)" />
</div>
</div>
</template>
</Select>
<br />
<br />
<Select aria-label="多选" dropdownClassName="components-select-demo-renderOptionItem" filter multiple :optionList="optionList" placeholder="多选" style="width: 320px" @search="inputValue = $event">
<template #optionItem="{ id, disabled, selected, label, focused, class: className, style, onClick, onMouseenter }">
<div
:id="id"
:aria-disabled="disabled"
:aria-selected="selected"
:class="[
'custom-option-render',
{
'custom-option-render-focused': focused,
'custom-option-render-disabled': disabled,
'custom-option-render-selected': selected,
},
className,
]"
role="option"
:style="style"
@click="onClick"
@mouseenter="onMouseenter"
>
<Checkbox :modelValue="selected" />
<div class="option-right">
<Highlight :searchWords="[inputValue]" :sourceString="String(label)" />
</div>
</div>
</template>
</Select>
</template>.components-select-demo-renderOptionItem {
.custom-option-render {
display: flex;
font-size: 14px;
line-height: 20px;
word-break: break-all;
padding-left: 12px;
padding-right: 12px;
padding-top: 8px;
padding-bottom: 8px;
color: var(--semi-color-text-0);
position: relative;
display: flex;
align-items: center;
cursor: pointer;
box-sizing: border-box;
.option-right {
margin-left: 8px;
display: inline-flex;
align-items: center;
}
&:active {
background-color: var(--semi-color-fill-1);
}
&-focused {
background-color: var(--semi-color-fill-0);
}
&-selected {
//font-weight: 700;
}
&-disabled {
color: var(--semi-color-disabled-text);
cursor: not-allowed;
}
&:first-of-type {
margin-top: 4px;
}
&:last-of-type {
margin-bottom: 4px;
}
}
}
API reference
Select Props
Props
| Property | Description | Type | Default |
|---|---|---|---|
| modelValue | The selected value, bound with v-model; an array in multiple mode. Passing it makes the Select controlled; undefined is treated as uncontrolled and reads defaultValue. | TypeSelectValue<T> | undefined |
| defaultValue | The initially selected value, read on mount only; an array in multiple mode. | TypeSelectValue<T> | semiGlobalDefault("Select", "defaultValue") |
| multiple | Whether multiple options can be selected. It decides the payload type of change and update:modelValue: an array in multiple mode, a single value or undefined otherwise. The global defaults cannot set it. | Multiple | undefined |
| optionList | Options as an array. Each item needs value and label (a string or number); other fields travel with the option record. A non-empty array takes precedence over the default slot; groups are not supported. | SelectOptionProps[] | semiGlobalDefault("Select", "optionList") |
| filter | Whether the Select is searchable. true turns search on with the default strategy, which matches options whose label (or group title) contains the input; a function receives the input value and the option and returns true for a match. | Typeboolean | ((inputValue: string, option: SelectOptionProps) => boolean) | undefined |
| remote | Whether search is remote. When on, typing does not filter locally; update optionList from the search event instead. | boolean | semiDefault("Select", "remote", false) |
| allowCreate | Whether items missing from the list can be created; use it together with filter. The create event fires on creation, and the createItem slot customizes the row. | boolean | semiDefault("Select", "allowCreate", false) |
| autoClearSearchValue | In a searchable multiple Select, whether the search keyword is cleared after an option is selected. | boolean | semiDefault("Select", "autoClearSearchValue", true) |
| autofocus | Whether the Select takes focus after mounting. | boolean | semiDefault("Select", "autofocus", false) |
| defaultOpen | Whether the dropdown is open when mounted. | boolean | semiDefault("Select", "defaultOpen", false) |
| clickToHide | Whether clicking the select box closes an open dropdown. | boolean | semiDefault("Select", "clickToHide", false) |
| defaultActiveFirstOption | Whether opening the dropdown highlights the first enabled option when nothing is selected (press Enter to select it). With a selected value, the first selected option is always highlighted. | boolean | semiDefault("Select", "defaultActiveFirstOption", true) |
| changeWithObject | A boolean attribute, not an event: when true, change, update:modelValue, modelValue and defaultValue use option objects, which must contain value and label. | boolean | semiDefault("Select", "changeWithObject", false) |
| max | The maximum number of selected options, in multiple mode only; beyond it nothing more can be selected and the exceed event fires. | number | semiGlobalDefault("Select", "max") |
| maxTagCount | In multiple mode, the most tags shown; the rest collapse into +N. | number | semiGlobalDefault("Select", "maxTagCount") |
| maxHeight | The maximum height of the option list; a number is in pixels, a string is used as is. When the virtual list height exceeds the default, set this to the same value to avoid a double scrollbar. | string | number | semiDefault("Select", "maxHeight", numbers.LIST_HEIGHT) |
| showRestTagsPopover | Whether hovering +N shows the remaining tags in a Popover once maxTagCount is exceeded. | boolean | semiDefault("Select", "showRestTagsPopover", false) |
| restTagsPopoverProps | Configuration of the Popover that shows the remaining tags, such as position and trigger. | PopoverProps | semiGlobalDefault("Select", "restTagsPopoverProps") |
| expandRestTagsOnClick | In multiple mode with maxTagCount, whether all tags are shown while the dropdown is open. | boolean | semiDefault("Select", "expandRestTagsOnClick", false) |
| ellipsisTrigger | In multiple mode with maxTagCount, whether the last tag is truncated when the width is short. It costs some performance, so avoid it in large forms. | boolean | semiDefault("Select", "ellipsisTrigger", false) |
| size | Size: small, default or large. | Size | semiGlobalDefault("Select", "size") |
| disabled | Whether the Select is disabled. | boolean | semiDefault("Select", "disabled", false) |
| borderless | Whether the Select has no border. | boolean | semiDefault("Select", "borderless", false) |
| validateStatus | Validation status: default, warning or error. It only affects styles such as the background color. | "default" | "error" | "warning" | "success" | semiGlobalDefault("Select", "validateStatus") |
| placeholder | Placeholder text shown while nothing is selected. | string | semiGlobalDefault("Select", "placeholder") |
| searchPlaceholder | Placeholder of the search input when it sits in the dropdown (searchPosition is dropdown). | string | semiGlobalDefault("Select", "searchPlaceholder") |
| searchPosition | Where the search input sits when search is on: trigger puts it in the select box, dropdown at the top of the list. With trigger the clear button also clears the search text; with dropdown it clears the selection only. | "trigger" | "dropdown" | semiDefault("Select", "searchPosition", "trigger") |
| loading | Whether the dropdown shows a loading indicator. | boolean | semiDefault("Select", "loading", false) |
| showArrow | Whether the dropdown arrow is shown. | boolean | semiDefault("Select", "showArrow", true) |
| showClear | Whether the clear button is shown. It appears in the select box when there is a selection or search text and the Select is enabled. | boolean | semiDefault("Select", "showClear", false) |
| insetLabelId | The id of the insetLabel element, which the combobox's aria-labelledby points at. The component generates one when omitted. | string | undefined |
| inputProps | Extra props of the search Input when search is on; listeners use Vue keys such as onFocus. Do not pass modelValue, defaultValue or onChange, which would override the Select's own state and search handling. | SelectInputProps | semiGlobalDefault("Select", "inputProps") |
| dropdownClassName | Class of the dropdown popup. | string | semiGlobalDefault("Select", "dropdownClassName") |
| dropdownStyle | Style of the dropdown popup, for example width. The style on the root element does not reach the popup. | StyleValue | semiGlobalDefault("Select", "dropdownStyle") |
| dropdownMatchSelectWidth | Whether the minimum width of the popup equals the select box. | boolean | semiDefault("Select", "dropdownMatchSelectWidth", true) |
| position | Where the popup opens; the values are those of the Tooltip position. | Type"top" | "bottom" | "left" | "right" | "topLeft" | "topRight" | "leftTop" | "leftBottom" | "rightTop" | "rightBottom" | "bottomLeft" | "bottomRight" | "leftTopOver" | "rightTopOver" | "leftBottomOver" | "rightBottomOver" | semiGlobalDefault("Select", "position") |
| spacing | The distance between the popup and the select box, in pixels. | number | { x: number; y: number; } | semiGlobalDefault("Select", "spacing") |
| motion | Whether the popup is animated. | boolean | semiDefault("Select", "motion", true) |
| autoAdjustOverflow | Whether the popup flips automatically when it would be clipped. | boolean | semiDefault("Select", "autoAdjustOverflow", true) |
| stopPropagation | Whether click events inside the popup stop propagating. | boolean | semiDefault("Select", "stopPropagation", true) |
| virtualize | Turns on list virtualization for many options. itemSize is the height of every row and is required; height defaults to 270 and width to 100%. | SelectVirtualize | semiGlobalDefault("Select", "virtualize") |
| preventScroll | Whether focusing prevents the browser from scrolling the element into view; applies to the component's own focus calls. | boolean | semiGlobalDefault("Select", "preventScroll") |
| id | The id of the trigger, from which the option ids derive. The component generates one when omitted; it does not read the global defaults. | string | undefined |
Events
| Event | Description | Callback parameters |
|---|---|---|
| update:modelValue | Emitted when the selection changes; used by v-model. The payload equals that of change, and it is emitted before change. | Type[value: SelectChangeValue<T, Multiple>] |
| change | Emitted when the selection changes. The payload is the value or undefined in single mode and an array in multiple mode; with changeWithObject it holds option objects. It shadows the native event of the same name on the root element. | Type[value: SelectChangeValue<T, Multiple>] |
| dropdownVisibleChange | Emitted when the dropdown opens or closes. Deactivating the component inside KeepAlive closes it and emits false, without a blur. | [visible: boolean] |
| search | Emitted when the search keyword changes, with the event that changed it: the input event while typing, a native MouseEvent when a click outside closes the list and clears it. There is no event when it comes from the ref's search or the trigger slot's onSearch. | [value: string, event?: Event | undefined] |
| select | Emitted when an option is selected; value is always the option's original value and option is its record. It shadows the native event of the same name on the root element. | [value: string | number, option: SelectOptionProps] |
| deselect | Emitted when an option is deselected, in multiple mode only; value is as in select. | [value: string | number, option: SelectOptionProps] |
| exceed | Emitted when a selection would exceed max, in multiple mode only, with the rejected option. | [option: SelectOptionProps] |
| create | Emitted when allowCreate is on and an option is created, with the new option record. | [option: SelectOptionProps] |
| clear | Emitted when the clear button is used by click or keyboard. | [] |
| focus | Emitted once when focus enters the Select, including its search input and clear button; moving within it does not emit again. It shadows the native event of the same name on the root element. | [event: FocusEvent] |
| blur | Emitted once when focus leaves the Select; a mouse press outside the open dropdown passes its mousedown event. It shadows the native event of the same name on the root element. | [event: FocusEvent | MouseEvent] |
| keydown | A key press, emitted after the Select has handled the key, so calling preventDefault in a listener does not affect the Select's own handling. It shadows the native event of the same name on the root element. | [event: KeyboardEvent] |
| listScroll | Emitted when the option list scrolls. | [event: Event] |
Slots
| Slot | Description | Scope parameters |
|---|---|---|
| default | The options. Only Select.Option and Select.OptGroup are accepted as direct children; v-for, v-if and template are unfolded. Unused while optionList is not empty. | any |
| prefix | A prefix in the select box. Text or an icon gets side spacing automatically; a custom node does not. | any |
| suffix | A suffix in the select box. Text or an icon gets side spacing automatically; a custom node does not. | any |
| insetLabel | A label inside the select box, which also names the combobox and the dropdown. It is not rendered, and does not name them, when a prefix is present. | any |
| arrowIcon | The dropdown arrow on the right; an empty slot hides it. With showClear and a value, hovering shows the clear button first. | any |
| clearIcon | The icon of the clear button, used when showClear is true. | any |
| emptyContent | Content shown when there are no options or the search finds none; an empty slot hides the empty state, and without the slot the locale text is shown. | any |
| outerTopSlot | Content at the top of the popup beside the option list; it does not scroll with the list and is always visible. | any |
| innerTopSlot | Content at the top inside the option list, visible when the list is scrolled to its top. | any |
| outerBottomSlot | Content at the bottom of the popup beside the option list; it does not scroll with the list and is always visible. | any |
| innerBottomSlot | Content at the bottom inside the option list, visible when the list is scrolled to its bottom. | any |
| optionItem | Replaces a whole option row. The parameters hold id, value, label, selected, focused, disabled, inputValue, class, style, onClick and onMouseenter. Put class, style and onMouseenter on the row element, and id together with role, aria-selected and aria-disabled on that same element. | SelectOptionItemSlotProps |
| createItem | Content of the row that creates an option from the keyword when allowCreate is on. The parameters are inputValue, focus and style; with a virtual list, apply style to the custom element. | SelectCreateItemSlotProps |
| selectedItem | A selected item: the content shown in the select box in single mode, or the content of a built-in tag in multiple mode. The parameters are option, index, disabled and onClose. | SelectSelectedItemSlotProps |
| tag | Replaces each tag in multiple mode, taking precedence over selectedItem when both are given. The parameters are those of selectedItem. | SelectSelectedItemSlotProps |
| trigger | Replaces the content of the trigger. The parameters hold the selected options as value, inputValue, placeholder, disabled, componentProps, and the onSearch, onClear and onRemove methods. When onClear is bound to a control inside the trigger, pass the click event so that click does not reopen the dropdown. To keep searching, set filter together with searchPosition as dropdown. | SelectTriggerSlotProps |
Exposes
| Name | Description | Type |
|---|---|---|
| None |
class, style, data-* and native listeners land on the root element, and style does not reach the dropdown popup (use dropdownStyle). aria-label, aria-labelledby, aria-describedby, aria-errormessage, aria-invalid and aria-required land on the combobox; once the search input is mounted it is the combobox, and these attributes move to it.
Option Props
An option is identified by its value, which should not repeat within one Select; labels may repeat
Props
| Property | Description | Type | Default |
|---|---|---|---|
| value | The value of the option, which identifies it; every option should declare one. | string | number | undefined |
| label | The text of the option, a string or number. Display and matching take label first, then the plain text of the default slot, then value; content with markup goes in the default slot and is displayed instead of label. | string | number | undefined |
| disabled | Whether the option is disabled. | boolean | undefined |
| showTick | Whether a tick icon is shown when the option is selected. | boolean | undefined |
| empty | Used by Select internally to render the empty-state row; callers do not set it. | boolean | undefined |
| selected | Used by Select internally to mark the option as selected; callers do not set it. | boolean | undefined |
| focused | Used by Select internally to mark the option as highlighted by keyboard or pointer; callers do not set it. | boolean | undefined |
| current | Used by Select and AutoComplete internally to mark the row that aria-activedescendant points at; callers do not set it. | boolean | undefined |
| inputValue | Used by Select internally as the search keyword highlighted in a plain-text label; callers do not set it. | string | undefined |
| semiOptionId | Used by Select internally as the id of the option row; callers do not set it. | string | undefined |
| prefixCls | Used by Select and AutoComplete internally as the CSS class prefix of the option row; callers do not set it. | string | cssClasses.PREFIX_OPTION |
Events
| Event | Description | Callback parameters |
|---|---|---|
| select | Used by Select internally; emitted when an enabled option row is clicked, with the option record and the click event. Listen to the select event of Select instead. | [option: SelectOptionProps, event: MouseEvent] |
| mouseenter | Used by Select internally; emitted when the pointer enters the row, to move the highlight. | [event: MouseEvent] |
Slots
| Slot | Description | Scope parameters |
|---|---|---|
| default | The content of the option. Plain text takes part in search highlighting; markup is rendered as is in the option row and filled back into the select box as is once selected, while search matches label, or value without a label. | any |
Exposes
| Name | Description | Type |
|---|---|---|
| None |
Select.Option is only read inside the default slot of Select, and its props become the option record. class, style and data-* land on the option row; other undeclared attributes never reach the DOM and travel with the option record in the payload of the select event, and of change once changeWithObject is on.
OptGroup Props
Props
| Property | Description | Type | Default |
|---|---|---|---|
| label | The text of the group title, a string or number, also matched by the default search; a title with markup uses the label slot. | string | number | undefined |
Events
| Event | Description | Callback parameters |
|---|---|---|
| None |
Slots
| Slot | Description | Scope parameters |
|---|---|---|
| default | The options of the group; only Select.Option is accepted as a direct child. | any |
| label | A custom group title, taking precedence over the label prop. | any |
Exposes
| Name | Description | Type |
|---|---|---|
| None |
Attrs such as class and style land on the group title element.
Methods
Select exposes the following methods through a template ref, typed as SelectHandle:
| Method | Instructions |
|---|---|
| open() | Manually open dropdown list |
| close() | Manually close dropdown list |
| focus() | Manually focus: a searchable Select focuses the search input and opens the dropdown list, otherwise it focuses the trigger without opening |
| clearInput() | Manually clear value of the search input |
| selectAll() | Select every shown, enabled option; multiple mode only |
| deselectAll() | Manually clear selected options |
| search(value: string, event?: Event) | Searches as if the value were typed into the search input, and the value is set to the input; without an event, the second parameter of the search event is undefined |
| rePosition() | Recomputes the dropdown position from the trigger's current position at once; the dropdown already follows scrolling, window resizing, trigger moves and size changes of the trigger or list, so this is rarely needed; following a trigger move lands a frame late, so call this to align within the same frame |
<script setup lang="ts">
import { useTemplateRef } from 'vue';
import { Select } from '@fibrous/semi-ui-vue';
import type { SelectHandle } from '@fibrous/semi-ui-vue';
const select = useTemplateRef<SelectHandle>('select');
const open = () => select.value?.open();
</script>
<template>
<Select ref="select" />
</template>
Accessibility
ARIA
- Following the ARIA 1.2 combobox pattern, exactly one element is the combobox at any time; the popup layer is a listbox and each option an option:
- Without search, or with the search input in the dropdown (
searchPosition="dropdown"), the Select trigger is a select-only combobox and the selected content is its value - With the search input in the trigger, the input itself is the combobox, with
aria-autocomplete="list", and the trigger has no role and no Tab stop. In single mode the input appears only while searching, so the trigger is the combobox otherwise; the input is empty until the user types, so the selected text is linked to it as its description witharia-describedby. In multiple mode the input is always there - A search input in the dropdown stays a text box with
aria-controls,aria-autocompleteandaria-activedescendant, named like the combobox
- Without search, or with the search input in the dropdown (
- The combobox takes its name from, in order:
aria-labelledby,aria-label, the rendered insetLabel (the combobox'saria-labelledbypoints at it, with an id the component generates wheninsetLabelIdis not given; with a prefix the insetLabel is not rendered and does not name it), and otherwise "Select" from the locale. Pass a name that matches the form label. The listbox and a search input in the dropdown use the same name source, never the combobox itself. The selected content is the value of the combobox and is not part of the name - The combobox has aria-haspopup, aria-expanded, and aria-controls properties, indicating its relationship with the popup layer
- When multiple selections are made, listbox aria-multiselectable is true, indicating that multiple selections are currently available
- aria-selected is true when Option is selected; aria-disabled is true when Option is disabled
- The options of an OptGroup with a label sit in a
role="group"named by the group title (aria-labelledby), so screen readers announce the group of an option; a virtualized list shows no group titles and has no groups - While the dropdown is open, aria-activedescendant points at the option focused from the keyboard, which ensures that it is recognized when the narration is spoken; with a fully custom option rendering, put the
idfrom the parameters on the option element (for more information, please refer to Managing Focus in Composites Using aria-activedescendant)
Keyboard and Focus
Select without Filter, or with the search box in the dropdown (searchPosition="dropdown"):
- After Select is focused, keyboard users can open the dropdown menu with
Space,Up Arrow,Down Arrow(includingAlt+Down Arrow) orEnter. With a selected value the focus goes to the first selected option, so pressing Enter right away keeps the value; without one the current highlight stays, starting on the first enabled option (defaultActiveFirstOptiondefaults to true) HomeandEndopen the dropdown menu and move the focus to the first and the last enabled option- Typing a character opens the dropdown menu and moves the focus to the next option that starts with it; characters typed in quick succession match as a whole, and typing the same character again cycles through the options that start with it
- When the dropdown menu is open:
- Use
Esckey orTabkey to close the menu - Use
Up ArroworDown Arrowto toggle options,HomeandEndto move to either end, and a typed character to move to an option that starts with it EnterorSpaceselects the focused option: a single Select selects it and collapses the panel, a multiple Select toggles it and stays open. While characters are being typed in quick succession,Spacejoins the search string instead of selecting. With the focus in the search box inside the dropdown,Home,End,Spaceand characters edit the search text without moving the option focus
- Use
- In a multiple Select with the focus on a selected tag, keys act on the tag only:
BackspaceandDeleteremove it, andEnterandSpaceneither open the dropdown menu nor change the value - When the focus is on the dropdown menu and the user uses an
innerBottomSlotorouterBottomSlotattribute with a custom slot with an interactive element:- You can use the
Tabkey to switch to these interactive elements - When the focus is on the first interactive element of the custom slot, use
Shift+Tabto return the focus to the Select box
- You can use the
Select with Filter function:
- When Select is focused, keyboard users can open dropdown menus with
Up ArroworDown ArroworEnterkeys. At this point, the focus is still on the Select box, the user can enter content, and can also use theup arrowordown arrowto switch options - When the dropdown menu is open:
Up ArrowandDown Arrowswitch options;Enterselects the focused option, collapsing the panel in a single Select and toggling it while staying open in a multiple Select;EscorTabcloses the menu.Home,End,Spaceand characters belong to the input in the Select box and edit the search text without moving the option focus - When the focus is on the Select box, and the user uses an
innerBottomSlotorouterBottomSlotproperty with a custom slot with an interactive element:- You can use the
Tabkey to switch to these interactive elements - When the focus is on the first interactive element of the custom slot, use
Shift+Tabto return the focus to the Select box
- You can use the
Clear button:
- With
showClear, a selected value or search text, and nodisabled, the trigger renders a clear button. It is a nativebuttonnamed "Clear selection" from the locale, shown on hover, while the dropdown is open, or while focus is inside the Select - From the Select box,
Tabmoves to the clear button;EnterorSpaceclears, as a mouse click does, and the focus goes back to the Select box
Content Guidelines
- Selector trigger
- Describe in 1-3 words the input that the user needs to make
- Use statement writing conventions (first letter uppercase, rest lowercase)
- Avoid punctuation and prepositions ("the", "an", "a")
- Labels need to be independent statements. Don't let the label be the first half of the statement and the option the second half of the statement.
- Use descriptive sentences, not indicative ones. Help text is available under the select box if the option needs more explanation.
- Selector options
- If there is no default option, use "Select" as placeholder copy
- Options should be in alphabetical order or other logical order to make it easier for users to find options
- Use statement writing conventions (first letter uppercase, rest lowercase), avoid commas and semicolons at the end of sentences
- Clearly articulate the purpose of the choice indicated by the option
Design Tokens
| Sass variable | Value | Usage |
|---|---|---|
| $transition_duration-select-bg | var(--semi-transition_duration-none) | 选择器-背景色-动画持续时间 |
| $transition_function-select-bg | var(--semi-transition_function-easeIn) | 选择器-背景色-过渡曲线 |
| $transition_delay-select-bg | var(--semi-transition_delay-none) | 选择器-背景色-延迟时间 |
| $transition_duration-select-border | var(--semi-transition_duration-none) | 选择器-边框-动画持续时间 |
| $transition_function-select-border | var(--semi-transition_function-easeIn) | 选择器-边框-过渡曲线 |
| $transition_delay-select-border | var(--semi-transition_delay-none) | 选择器-边框-延迟时间 |
| $transition_duration-select_option-bg | var(--semi-transition_duration-none) | 选择器-选项-动画持续时间 |
| $transition_function-select_option-bg | var(--semi-transition_function-easeIn) | 选择器-选项-过渡曲线 |
| $transition_delay-select_option-bg | var(--semi-transition_delay-none) | 选择器-选项-延迟时间 |
| $transform_scale-select | var(--semi-transform_scale-none) | 选择框-变大 |
| $transform_rotate-select-arrow | var(--semi-transform_rotate-none) | 选择框-箭头-旋转 |
| $color-select-bg-default | var(--semi-color-fill-0) | 选择器输入框背景色 - 默认态 |
| $color-select-bg-hover | var(--semi-color-fill-1) | 选择器输入框背景色 - 悬停态 |
| $color-select-bg-active | var(--semi-color-fill-2) | 选择器输入框背景色 - 按下态 |
| $color-select-bg-focus | var(--semi-color-fill-0) | 选择器输入框背景色 - 聚焦态 |
| $color-select-border-default | transparent | 选择器输入框描边颜色 |
| $color-select-border-hover | $color-select-border-default | 选择器输入框描边颜色 - 悬浮 |
| $color-select-border-active | var(--semi-color-focus-border) | 选择器输入框描边颜色 - 按下态 |
| $color-select-border-focus | $color-select-border-active | 选择器输入框描边颜色 - 选中态 |
| $color-select_dropdown_input-border | $color-select-border-default | 下拉搜索框底部描边颜色 |
| $color-select_warning-bg-default | var(--semi-color-warning-light-default) | 警示选择器输入框背景色 - 默认态 |
| $color-select_warning-border-default | var(--semi-color-warning-light-default) | 警示选择器输入框描边颜色 - 默认态 |
| $color-select_warning-bg-hover | var(--semi-color-warning-light-hover) | 警示选择器输入框背景色 - 悬停态 |
| $color-select_warning-border-hover | var(--semi-color-warning-light-hover) | 警示选择器输入框描边颜色 - 悬停态 |
| $color-select_warning-bg-focus | var(--semi-color-warning-light-default) | 警示选择器输入框背景色 - 选中态 |
| $color-select_warning-border-focus | var(--semi-color-warning) | 警示选择器输入框描边颜色 - 选中态 |
| $color-select_warning-bg-active | var(--semi-color-warning-light-active) | 警示选择器输入框背景色 - 按下态 |
| $color-select_warning-border-active | var(--semi-color-warning-light-active) | 警示选择器输入框描边颜色 - 按下态 |
| $color-select_danger-bg-default | var(--semi-color-danger-light-default) | 报错选择器输入框背景色 - 默认态 |
| $color-select_danger-border-default | var(--semi-color-danger-light-default) | 报错选择器输入框描边颜色 - 默认态 |
| $color-select_danger-bg-hover | var(--semi-color-danger-light-hover) | 报错选择器输入框背景色 - 悬停态 |
| $color-select_danger-border-hover | var(--semi-color-danger-light-hover) | 报错选择器输入框描边颜色 - 悬停态 |
| $color-select_danger-bg-focus | var(--semi-color-danger-light-default) | 报错选择器输入框背景色 - 选中态 |
| $color-select_danger-border-focus | var(--semi-color-danger) | 报错选择器输入框描边颜色 - 选中态 |
| $color-select_danger-bg-active | var(--semi-color-danger-light-active) | 报错选择器输入框背景色 - 按下态 |
| $color-select_danger-border-active | var(--semi-color-danger-light-active) | 报错选择器输入框描边颜色 - 按下态 |
| $color-select_default-border-focus | var(--semi-color-focus-border) | 默认选择器输入框描边颜色 - 选中态 |
| $color-select_main-text-default | var(--semi-color-text-0) | 选择器输入框回填内容文本颜色 |
| $color-select-icon-default | var(--semi-color-text-2) | 选择器输入框图标颜色 |
| $color-select_clearBtn-text-default | var(--semi-color-text-2) | 选择器输入框清空按钮颜色 - 默认态 |
| $color-select_clearBtn-text-hover | var(--semi-color-primary) | 选择器输入框清空按钮颜色 - 悬停态 |
| $color-select_input_disabled-bg | var(--semi-color-disabled-fill) | 禁用选择器输入框背景色 |
| $color-select_input_disabled-border-focus | transparent | 禁用选择器输入框描边颜色 - 聚焦态 |
| $color-select_input_disabled-text | var(--semi-color-disabled-text) | 禁用选择器输入框回填内容文字颜色 |
| $color-select_input_disabled-bg-hover | var(--semi-color-disabled-fill) | 禁用选择器输入框背景色 - 悬停态 |
| $color-select_input_disabled-bg-focus | var(--semi-color-disabled-fill) | 禁用选择器输入框背景色 - 聚焦态 |
| $color-select_input_placeholder-text | var(--semi-color-text-2) | 选择器输入框占位文本文字颜色 |
| $color-select_option_main-text | var(--semi-color-text-0) | 选择器下拉菜单选项文本颜色 |
| $color-select_option_keyword-text | var(--semi-color-primary) | 选择器下拉菜单选项匹配搜索结果文本颜色 |
| $color-select_option-icon-default | transparent | 选择器下拉菜单选项图标颜色 - 默认态 |
| $color-select_option-bg-hover | var(--semi-color-fill-0) | 选择器下拉菜单选项背景颜色 - 悬停态 |
| $color-select_option-bg-active | var(--semi-color-fill-1) | 选择器下拉菜单选项背景颜色 - 按下态 |
| $color-select_option_disabled-text | var(--semi-color-disabled-text) | 禁用选择器下拉菜单选项文字颜色 |
| $color-select_option-icon-active | var(--semi-color-text-2) | 选择器下拉菜单选项图标颜色 - 选中态 |
| $color-select_option-border-default | var(--semi-color-border) | 选择器下拉菜单分组标题分割线颜色 |
| $color-select-option-bg-selected | transparent | 选择器下拉菜单选项背景颜色 - 选中态 |
| $color-select_create_tips-text | var(--semi-color-text-2) | 选择器下拉菜单新建选项提示文本颜色 |
| $color-select_group-text | var(--semi-color-text-2) | 选择器下拉菜单分组标题文本颜色 |
| $color-select_prefix_suffix_text-default | var(--semi-color-text-2) | 选择器输入框前后缀文本颜色 |
| $height-select_large | $height-control-large | 选择器输入框高度 - 大尺寸 |
| $height-select_small | $height-control-small | 选择器输入框高度 - 小尺寸 |
| $height-select_default | $height-control-default | 选择器输入框高度 - 默认尺寸 |
| $width-select_option_tick | $width-icon-small | 选择器下拉菜单项选中对勾图标大小 |
| $width-select-border | 1px | 选择器输入框描边宽度 |
| $width-select_arrow | 32px | 选择器输入框下拉箭头宽度 |
| $width-select_arrow_empty | 12px | 选择器输入框下拉箭头为空时(有suffix icon)宽度 |
| $width-select_clear-icon | 32px | 选择器输入框清空按钮宽度 |
| $width-select_group_top-border | $border-thickness-control | 选择器下拉菜单分组标题描边宽度 |
| $height-select_multiple_input_small | 20px | 小尺寸多项选择器输入框Input框高度 |
| $height-select_multiple_input_default | 24px | 默认多项选择器输入框Input框高度 |
| $height-select_multiple_input_large | 24px | 大尺寸多项选择器输入框Input框高度 |
| $width-select-border-hover | $width-select-border | 选择器输入框描边宽度 - 悬浮 |
| $width-select-border-focus | $width-select-border-hover | 选择器输入框描边宽度 - 按下 |
| $width-select-border-active | $width-select-border-focus | 选择器输入框描边宽度 - 选中 |
| $spacing-select_option_tick-marginRight | $spacing-tight | 选择器下拉菜单选中对勾右侧外边距 |
| $spacing-select_prefix_suffix_text-marginX | $spacing-base-tight | 选择器输入框前后缀文本水平内边距 |
| $spacing-select_prefix_suffix_text-marginY | 0px | 选择器输入框前后缀文本垂直内边距 |
| $spacing-select_prefix_suffix_icon-marginX | $spacing-tight | 选择器输入框前后缀图标水平内边距 |
| $spacing-select_prefix_suffix_icon-marginY | 0px | 选择器输入框前后缀图标垂直内边距 |
| $spacing-select_create_tips-marginRight | $spacing-extra-tight | 创建新选项右侧外边距 |
| $spacing-select_group-marginTop | $spacing-extra-tight | 选择器下拉菜单分组标题顶部外边距 |
| $spacing-select_group-paddingTop | $spacing-base-tight | 选择器下拉菜单分组标题顶部内边距 |
| $spacing-select_group-paddingBottom | $spacing-extra-tight | 选择器下拉菜单分组标题底部内边距 |
| $spacing-select_group-paddingLeft | $spacing-base-tight + $width-select_option_tick + $spacing-select_option_tick-marginRight | 选择器下拉菜单分组标题左侧内边距 |
| $spacing-select_group-paddingRight | $spacing-base | 选择器下拉菜单分组标题右侧内边距 |
| $spacing-select_loading_wrapper-paddingLeft | $spacing-base | 选择器加载左侧内边距 |
| $spacing-select_loading_wrapper-paddingRight | $spacing-base | 选择器加载右侧内边距 |
| $spacing-select_loading_wrapper-paddingTop | $spacing-tight | 选择器加载顶部内边距 |
| $spacing-select_loading_wrapper-paddingBottom | $spacing-tight | 选择器加载底部内边距 |
| $spacing-select_multiple_content_wrapper_empty-marginLeft | $spacing-tight | 多项选择器空回填内容为空时左侧内边距 |
| $spacing-select_multiple_selection-marginLeft | $spacing-extra-tight | 多项选择器回填内容左侧内边距 |
| $spacing-select_option-paddingLeft | $spacing-base-tight | 选择器下拉菜单项左侧内边距 |
| $spacing-select_option-paddingRight | $spacing-base-tight | 选择器下拉菜单项右侧内边距 |
| $spacing-select_option-paddingTop | $spacing-tight | 选择器下拉菜单项顶部内边距 |
| $spacing-select_option-paddingBottom | $spacing-tight | 选择器下拉菜单项底部内边距 |
| $spacing-select_tag-marginTop | $spacing-super-tight - 1px | 多项选择器标签顶部外边距 |
| $spacing-select_tag-marginRight | $spacing-extra-tight | 多项选择器标签右侧外边距 |
| $spacing-select_tag-marginBottom | $spacing-super-tight - 1px | 多项选择器标签底部外边距 |
| $spacing-select_selection-marginLeft | $spacing-base-tight | 选择器内容区左侧外边距 |
| $spacing-select_option_list-paddingTop | $spacing-extra-tight | 选择器内容区顶部内边距 |
| $spacing-select_option_list-paddingRight | 0px | 选择器内容区右侧内边距 |
| $spacing-select_option_list-paddingBottom | $spacing-extra-tight | 选择器内容区底部内边距 |
| $spacing-select_option_list-paddingLeft | 0px | 选择器内容区左侧内边距 |
| $spacing-select_dropdown_input_paddingTop | 8px | 下拉搜索框顶部内边距 |
| $spacing-select_dropdown_input_paddingBottom | 8px | 下拉搜索框底部内边距 |
| $spacing-select_dropdown_input_paddingRight | 12px | 下拉搜索框右侧内边距 |
| $spacing-select_dropdown_input_paddingLeft | 12px | 下拉搜索框左侧内边距 |
| $radius-select | var(--semi-border-radius-small) | 选择器输入框圆角 |
| $radius-select_option | 0px | 选择器待选项圆角 |
| $font-select-fontWeight | $font-weight-regular | 选择器文本字重 |
| $font-select_keyword-fontWeight | 600 | 选择器搜索结果命关键词中文本字重 |
| $font-select_prefix_suffix-fontWeight | $font-weight-bold | 选择器输入框前后缀文本字重 |
| $opacity-select_selection_text_inactive | 0.4 |
TypeScript Generic Support
Select is a generic component with two generic parameters: T, the type of an option's value (the option object when changeWithObject is set), and Multiple, the type of the multiple prop. The payload of change and update:modelValue is T | undefined in single mode and T[] in multiple mode; when multiple is a boolean variable it is T | T[] | undefined. The payload of select and deselect is the option's raw value (string | number), whatever T is. Both parameters are usually inferred from modelValue and multiple; the global defaults cannot set multiple, because giving it a default would break that inference.
<script setup lang="ts">
import { ref } from 'vue';
import { Select } from '@fibrous/semi-ui-vue';
// T is inferred from modelValue: string
const value = ref<string | undefined>();
// In multiple mode, modelValue is string[]
const values = ref<string[]>([]);
</script>
<template>
<Select v-model="value">
<Select.Option value="option1">Option 1</Select.Option>
<Select.Option value="option2">Option 2</Select.Option>
</Select>
<Select v-model="values" multiple>
<Select.Option value="option1">Option 1</Select.Option>
<Select.Option value="option2">Option 2</Select.Option>
</Select>
</template>
FAQ
-
Searchable Select, using remote data to dynamically update the
optionList, why sometimes there is no data before the asynchronous request is completed?
Please check whetherremoteis turned on. If remote is not turned on, the input value of the input box will be compared with the current optionList by default. If there is no match, no data will be displayed.
You can turn off matching filtering on the current local data by turning on remote. -
Will Select automatically limit the width of the drop-down menu?
MinWidth will be given, but width will not be written dead. If necessary, you can add it yourself through dropdownStyle. -
Why is the blur event not fired after a radio selection option?
Before V2.17.0, after Select radio is selected, the blur event of Select will be triggered. After V2.17.0, Select has added A11y support, which will not trigger Select's blur event. In single-selection selection, the Select floating layer is closed, and the focus is still on the trigger (at this time, the Select floating layer can be opened again by pressing the Enter key) No matter single selection or multiple selection, press Esc, only the Select floating layer is closed, and the trigger keeps the focus (the Select floating layer can be opened again by pressing the Enter key at this time)