--- localeCode: en-US order: 25 category: Input title: Select subTitle: Select icon: doc-select width: 60% brief: The user can select one or more options from a set of options through the Select selector and present the final selection result --- ## Demos ### How to import ```jsx import import { Select } from '@douyinfe/semi-ui'; const Option = Select.Option; ``` ### Basic Usage Each Option tag must declare the `value` attribute, and the Option `children` content will be rendered to the drop-down list ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => ( <>



) ``` ### Pass Option as an array You can pass an array of objects directly through `optionList`. Each object must contain the value / label attribute. ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => { const list = [ { value: 'abc', label: 'Semi' }, { value: 'hotsoon', label: 'Hotsoon' }, { value: 'pipixia', label: 'Pipixia' }, { value: 'toutiao', label: 'TooBuzz' }, ]; return ; }; ``` ### Multi-choice 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 Configuration `max` Properties can limit the maximum number of options and cannot be selected beyond the maximum limit, while triggering`On Exceed`callback ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => ( <>



) ``` ### With Group Grouping Option with `OptGroup`(Only supports the declaration of children through jsx, and does not support pass in through optionList) ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => ( ) ``` ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => { const data = [ { label: 'Asia', children: [ { value: 'a-1', label: 'China' }, { value: 'a-2', label: 'Koera' }, ], }, { label: 'Europe', children: [ { value: 'b-1', label: 'Germany' }, { value: 'b-2', label: 'France' }, ], }, { label: 'South America', children: [{ value: 'c-1', label: 'Peru' }], }, ]; return ( ); }; ``` ### Different sizes Size: small / default / large ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => ( <>



) ``` ### Different validate status validateStatus: default / warning / error ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => ( <>



) ``` ### Configure Prefix, Suffix, Clear Button - You can pass the selection box prefix through `prefix`, the selection box suffix through `suffix`, for text or React Node The left and right padding is automatically brought when the content passed in by prefix and reactix is text or Icon. If it is a custom ReactNode, 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` ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; import { IconVigoLogo, IconGift } from '@douyinfe/semi-icons'; () => ( <>

) ``` ### Select with inset label By setting`insetLabel`, you can set a label for Select, you can pass in string or ReactNode When the incoming type is ReactNode, you need to handle the padding between the label and the text. ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => { const list = [ { value: 'abc', label: 'Semi' }, { value: 'capcut', label: 'Capcut' }, { value: 'xigua', label: 'BuzzVideo' }, ]; return ( <>

); }; ``` ### 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. Use`innerTopSlot` or `outerTopSlot` to pass the custom node, which will be rendered at the top of the pop-up layer. Use`innerBottomSlot` or `outerBottomSlot` instead at the bottom. - `innerTopSlot` and `innerBottomSlot` will be rendered inside the Option List - `outerTopSlot` and `outerBottomSlot` will be rendered to level with the option List ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; import { IconClock } from '@douyinfe/semi-icons'; () => { let selectStyle = { width: 180, margin: 20 }; let innerSlotStyle = { backgroundColor: '#FFF', height: '40px', color: '#0077FA', display: 'flex', justifyContent: 'center', alignItems: 'center', cursor: 'pointer', }; let innerSlotNode =
No suitable product?
; let outSlotStyle = { backgroundColor: 'whitesmoke', height: '29px', display: 'flex', justifyContent: 'center', alignItems: 'center', cursor: 'pointer', }; let outSlotNode = (
More recently viewed pages
); return (

outerBottomSlot:

innerBottomSlot:

); }; ``` Using outerTopSlot to insert content ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; class Demo extends React.Component { constructor(props) { super(props); this.state = { key: 'component', }; this.list = { component: [ { value: 'select', label: 'Select' }, { value: 'tabs', label: 'Tabs' }, { value: 'avatar', label: 'Avatar' }, { value: 'button', label: 'Button' }, ], design: [ { value: 'color', label: 'Color' }, { value: 'dark', label: 'Dark Mode' }, { value: 'icon', label: 'Icon' }, { value: 'font', label: 'Topography' }, ], feedback: [ { value: 'faq', label: 'FAQ' }, { value: 'join', label: 'Join Chat Group' }, { value: 'hornbill', label: 'Hornbill' }, ], }; this.handleTabClick = this.handleTabClick.bind(this); } handleTabClick(itemKey) { this.setState({ key: itemKey }); } render() { const { key } = this.state; const tabStyle = { cursor: 'pointer', marginRight: 12, paddingBottom: 4, }; const tabActiveStyle = { ...tabStyle, borderBottom: '1px solid var(--semi-color-primary)', fontWeight: 700, }; const tabWrapper = { display: 'flex', paddingTop: 8, paddingLeft: 32, borderBottom: '0.5px solid var(--semi-color-border)', }; const tabOptions = [ { itemKey: 'component', label: 'Components' }, { itemKey: 'design', label: 'Design' }, { itemKey: 'feedback', label: 'Feedback' }, ]; const outerTopSlotNode = (
{tabOptions.map((item, index) => { style = item.itemKey === key ? tabActiveStyle : tabStyle; return (
this.handleTabClick(item.itemKey)}> {item.label}
); })}
); return (
Semi Capcut BuzzVideo ); }; ``` ### Linkage Select If it is a complex linkage with a hierarchical relationship, it is recommended to use Cascader components directly ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; class Link extends React.Component { get continents() { return ['Asia', 'Europe']; } get maps() { return { Asia: ['China', 'Korea'], Europe: ['United Kingdom', 'France', 'Germany'], }; } constructor() { super(); this.state = { continents: this.continents, maps: this.maps, countrys: this.maps[this.continents[0]], country: this.maps[this.continents[0]][0], }; this.continentsChange = this.continentsChange.bind(this); this.countryChange = this.countryChange.bind(this); } continentsChange(newContinents) { const { maps } = this.state; this.setState({ countrys: maps[newContinents], country: maps[newContinents][0] }); } countryChange(country) { this.setState({ country }); } render() { const { continents, countrys, country } = this.state; return ( ); } } ``` ### 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 ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => ( <>

) ``` ### Remote search A multi-select example with remote search, request debounce, loading status. - Use `filter` turn on the search capability. - Use `remote` to disabled local filter - Dynamic Update `optionList` after `onSearch` callback - Update `loading` when fetching data / finish - Use controlled value attribute ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; import { debounce } from 'lodash-es'; class SearchDemo extends React.Component { constructor() { super(); this.state = { Loading: false, optionList: [ { value: 'abc', label: 'Semi', type: 1 }, { value: 'capcut', label: 'Capcut', type: 2 }, { value: 'xigua', label: 'BuzzVideo', type: 4 }, ], value: '', multipleValue: [], }; this.handleSearch = debounce(this.handleSearch, 800).bind(this); this.onChange = this.onChange.bind(this); this.onMultipleChange = this.onMultipleChange.bind(this); } handleSearch(inputValue) { this.setState({ loading: true }); let length = Math.ceil(Math.random() * 100); let result = Array.from({ length }, (v, i) => { return { value: inputValue + i, label: inputValue + '-new line-' + i, type: i + 1 }; }); setTimeout(() => { this.setState({ optionList: result, loading: false }); }, 2000); } onChange(value) { this.setState({ value }); } onMultipleChange(multipleValue) { this.setState({ multipleValue }); } render() { const { loading, optionList, value, multipleValue } = this.state; return (


); } } ``` ### 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. ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => { function search(sugInput, option) { // Search for both label and value let label = option.label.toUpperCase(); let value = option.value.toUpperCase(); let sug = sugInput.toUpperCase(); return label.includes(sug) || value.includes(sug); } return ( ); }; ``` ### Custom selection rendering By default, the content of `option.label` or `option.children` will be backfilled into the selection box when the option is selected. But you can customize the rendering of the selection box through the `renderSelectedItem` function - Select: `renderSelectedItem(optionNode: object) => content: ReactNode` - Multiple Select: `renderSelectedItem(optionNode: object, { index: number, onClose: function }) => { isRenderInTag: boolean, content: ReactNode }` - When `isRenderInTag` is true, content will automatically wrapped in `Tag` rendering (with background color and close button) - When `isRenderInTag` is false, it renders the returned content directly ```jsx live=true import React from 'react'; import { Select, Avatar, Tag } from '@douyinfe/semi-ui'; class CustomRender extends React.Component { constructor() { super(); this.state = { list: [ { "name": "XiaKeMan", "email": "xiakeman@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg"}, { "name": "ShenYue", "email": "shenyue@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg"}, { "name": "QuChenYi", "email": "quchenyi@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/8bd8224511db085ed74fea37205aede5.jpg"}, { "name": "WenJiaMao", "email": "wenjiamao@example.com", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png"}, ] }; } renderSelectedItem(optionNode) { return (
{optionNode.abbr} {optionNode.email}
) } // avatarSrc & avatarShape are supported after 1.6.0 renderMultipleWithCustomTag(optionNode, { onClose }) { let content = ( {optionNode.name} ); return { isRenderInTag: false, content }; } renderMultipleWithCustomTag2(optionNode, { onClose }) { let content = ( {optionNode.name} ); return { isRenderInTag: false, content }; } renderCustomOption(item) { let optionStyle = { display: 'flex', paddingLeft: 24, paddingTop: 10, paddingBottom: 10 } return (
{item.name}
{item.email}
) } render() { const { list } = this.state; return ( ); } } ``` ### 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` ```jsx live=true import React from 'react'; import { Select } from '@douyinfe/semi-ui'; () => ( ) ``` ### Dynamic Modification Options If you need to update Options dynamically, you should use controlled value ```jsx live=true import React from 'react'; import { Select, Button } from '@douyinfe/semi-ui'; () => { let [options, setOptions] = useState([1, 2, 3, 4]); function add() { let length = Math.ceil(Math.random() * 10); let newOptions = Array.from({ length }, (v, i) => i + 1); setOptions(newOptions); } return ( <>

); }; ``` ### Get all attribute of selected option By default, through `onChange` uou can only get value attribute of selected option. If you need to take other attributes of the selected option, you can use `onChangeWithObject` Properties At this time, the argument of `onChange` will be object, containing various attributes of selected option, eg: `onChange({ value, label, ...rest })` Note that when onChange With Object is set to true,`defaultValue`/`Value`it should also be object and must have `value` key ```jsx live=true import React from 'react'; import { Select, TextArea } from '@douyinfe/semi-ui'; () => { const list = [ { value: 'abc', label: 'Semi', type: 1 }, { value: 'capcut', label: 'Capcut', type: 2 }, { value: 'xigua', label: 'BuzzVideo', type: 3 }, ]; const [cbValue, setCbValue] = useState(); const [multipleCbValue, setMultipleCbValue] = useState(); const onChange = value => { setCbValue(value); console.log(value); }; const onMultipleChange = value => { setMultipleCbValue(value); console.log(value); }; return (

onChang callback: