UNPKG

@douyinfe/semi-ui

Version:

A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.

1,629 lines (1,503 loc) 85.1 kB
--- localeCode: en-US order: 36 category: Input title: Cascader subTitle: Cascade icon: doc-cascader brief: Used to select an option under a multi-level classification. --- ## Usage scenarios Differences from TreeSelect component: - TreeSelect: The core value lies in **target node**. The structure is to facilitate users to quickly filter out target options. The final node is what the user wants. It is commonly used in file/folder selection, organizational structure, permission allocation and other scenarios. - Cascader: The core selection value lies in the **path**. What the user selects is not an isolated point, but a complete path from root to leaf, which is often used in scenarios such as geographical location and product classification. ## Demos ### How to import ```jsx import import { Cascader } from '@douyinfe/semi-ui'; ``` ### Basic Usage Basic usage, only leaf nodes can be selected by default. ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <Cascader style={{ width: 400 }} treeData={treeData} placeholder="Please select" /> ); }; ``` ### Multiple Set `multiple` to make multiple selections. ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <Cascader defaultValue= {['impressionism', 'visualArts', 'Monet']} style={{ width: 400 }} treeData={treeData} placeholder="Please select" multiple /> ); }; ``` ### Searchable Use `filterTreeNode` to support search input. By default, the `label` value is searched (using the includes method of the string for matching, case-insensitive). You can specify other attribute values ​​​​through `treeNodeFilterProp` to search. For example, If `label` is ReactNode, you can use other fields in treeData to store plain text, and specify the field for search through `treeNodeFilterProp`. The default search results will only display the paths of leaf nodes. If you want to display more results, you can set `filterLeafOnly` to `false`. ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; const labelNodeTreeData = [{ label: <Tooltip content="Other info">Impressionism</Tooltip>, labelText: 'Impressionism', value: 'impressionism', children: [ { label: <Tooltip content="Other info">Visual Arts</Tooltip>, labelText: 'Visual Arts', value: 'visualArts', children: [ { label: <Tooltip content="Other info">Claude Monet</Tooltip>, labelText: 'Claude Monet', value: 'Monet', }, { label: <Tooltip content="Other info">'Pierre-Auguste Renoir</Tooltip>, labelText: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: <Tooltip content="Other info">Édouard Manet</Tooltip>, labelText: 'Édouard Manet', value: 'Manet', }, ], }, { label: <Tooltip content="Other info">Music</Tooltip>, labelText: 'Music', value: 'music', children: [ { label: <Tooltip content="Other info">Claude Debussy</Tooltip>, labelText: 'Claude Debussy', value: 'Debussy', }, { label: <Tooltip content="Other info">Maurice Ravel</Tooltip>, labelText: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <div> <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Search in label by default" filterTreeNode /> <br/> <br/> <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Search in value" filterTreeNode treeNodeFilterProp='value' /> <br/> <br/> <Typography.Title heading={6}>filterLeafOnly=false:</Typography.Title> <Cascader style={{ width: 300 }} treeData={treeData} placeholder="filterLeafOnly=false" filterTreeNode filterLeafOnly={false} /> <br/> <br/> <Typography.Title heading={6}>Label is ReactNode, specify other attributes to search</Typography.Title> <Cascader style={{ width: 300 }} treeData={labelNodeTreeData} placeholder="Search for labelText" filterTreeNode treeNodeFilterProp='labelText' /> </div> ); }; ``` ### Searchable Multiple Selection When multiple selection and search are supported at the same time, in this scenario, you can delete the corresponding selected item by pressing the BackSpace key. ```jsx live=true import React, { useState } from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const [value, setValue] = useState(['impressionism', 'visualArts', 'Monet']); const onChange = (newValue) => { setValue(newValue); }; const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Please select" value={value} multiple filterTreeNode onChange={onChange} /> ); }; ``` Filtered data can be sorted using `filterSorter`, `filterSorter` is available since v2.28.0. ```jsx live=true import React, { useState } from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Product', value: 'Product', children: [ { label: 'Semi-Material', value: 'Semi-Material', }, { label: 'Semi-DSM', value: 'Semi-DSM', }, { label: 'Semi', value: 'Semi', }, { label: 'Semi-C2D', value: 'Semi-C2D', }, { label: 'Semi-D2C', value: 'Semi-D2C', }, ], } ]; return ( <div> <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Enter s to view the sorting effect" filterTreeNode filterSorter={(first, second, inputValue) => { const firstData = first[first.length - 1]; const lastData = second[second.length - 1]; if (firstData.label === inputValue) { return -1; } else if (lastData.label === inputValue) { return 1; } else { return firstData.label < lastData.label ? -1 : 1; } }} /> </div> ); }; ``` If you want to customize the rendering options after the search, you can use `filterRender` to achieve custom rendering of the entire line. The `filterRender` is available since v2.28.0, parameters are as follows: ``` tsx interface filterRenderProps { className: string; inputValue: string; // Search bar search content disabled: boolean; // Whether to disable data: CascaderData[]; // Search result data selected: boolean; // Selected state when single selection checkStatus: { // Checked state when multiple selection checked: boolean; halfChecked: boolean; }; onClick: (e: React.MouseEvent) => void; // Callback when clicked option in single selection onCheck: (e: React.MouseEvent) => void; // Callback when clicked option in multiple selection } ``` The example is as follows ```jsx live=true import React, { useState } from 'react'; import { Cascader, Typography, Checkbox } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Semi', value: 'Semi', children: [ { label: 'Semi-Material Semi-Material Semi-Material Semi-Material', value: 'Semi-Material', }, { label: 'Semi-DSM Semi-DSM Semi-DSM Semi-DSM', value: 'Semi-DSM', }, { label: 'Semi Design Semi Design Semi Design Semi Design', value: 'Semi Design', }, { label: 'Semi-C2D Semi-C2D Semi-C2D Semi-C2D Semi-C2D', value: 'Semi-C2D', }, { label: 'Semi-D2C Semi-D2C Semi-D2C Semi-D2C Semi-D2C ', value: 'Semi-D2C', }, ], } ]; const { Text } = Typography; const renderSearchOptionSingle = (props) => { const { className, data, onClick, onKeyPress, selected } = props; return ( <li className={className} style={{ justifyContent: 'flex-start' }} role="treeitem" onClick={onClick} onKeyPress={onKeyPress} > <Text ellipsis={{ showTooltip: { opts: { style: { wordBreak: 'break-all' } } } }} style={{ width: 270, color: selected ? 'var(--semi-color-primary)': undefined }} > {data.map(item => item.label ).join(' / ')} </Text> </li> ); }; const renderSearchOptionMultiple = (props) => { const { className, data, checkStatus, onClick, onKeyPress } = props; return ( <li className={className} style={{ justifyContent: 'flex-start' }} role="treeitem" onClick={onCheck} onKeyPress={onKeyPress} > <Checkbox onChange={onCheck} indeterminate={checkStatus.halfChecked} checked={checkStatus.checked} style={{ marginRight: 8 }} /> <Text ellipsis={{ showTooltip: { opts: { style: { wordBreak: 'break-all' } } } }} style={{ width: 250 }} > {data.map(item => item.label).join(' / ')} </Text> </li> ); }; return ( <div> <p>Mouse over the option to view the complete content of the omitted text</p> <br /> <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Single selection, enter s" filterTreeNode filterRender={renderSearchOptionSingle} /> <br /> <Cascader multiple style={{ width: 300, marginTop: 20 }} treeData={treeData} placeholder="Multiple selection, enter s" filterTreeNode filterRender={renderSearchOptionMultiple} /> </div> ); }; ``` If there are a lot of options in the search results, you can optimize performance by setting virtualizeInSearch to enable the virtualization of the search result panel. virtualizeInSearch has been available since v2.44.0. virtualizeInSearch is an object containing the following values: - height: Option list height value - width: Option list width value - itemSize: The height of each row of Option ```jsx live=true import React from 'react'; import { Cascader, Checkbox, Typography } from '@douyinfe/semi-ui'; () => { const treeData = useMemo(() => ( ['Generic', 'Scene'].map((label, m) => ({ label: label, value: m, children: new Array(100).fill(0).map((item, n)=> ({ value: `${m}-${n}`, label: `${m}-${n} level one`, children: new Array(20).fill(0).map((item, o)=> ({ value: `${m}-${n}-${o}`, label: `${m}-${n}-${o} level two detail info`, })), })) })) ), []); let virtualize = { // The height is the panel's default height of 180px minus the upper and lower padding 2 * 8px height: 172, width: 320, itemSize: 36, }; const filterRender = useCallback((props) => { const { data, onCheck, checkStatus, className } = props; return ( <div key={data.value} className={className} style={{ justifyContent: 'start', padding: '8px 16px 8px 12px', boxSizing: 'border-box' }} > <Checkbox onChange={onCheck} indeterminate={checkStatus.halfChecked} checked={checkStatus.checked} style={{ marginRight: 8 }} /> <Typography.Text ellipsis={{ showTooltip: { opts: { style: { wordBreak: 'break-all' } } } }} style={{ maxWidth: 260 }} > {data.map(item => item.label).join(' | ')} </Typography.Text> </div> ); }, []); return ( <Cascader multiple filterTreeNode style={{ width: 320 }} treeData={treeData} placeholder="Enter generic or scene to search" virtualizeInSearch={virtualize} filterRender={filterRender} /> ); }; ``` ### Limit Tags Displayed When multiple selections, you can use `maxTagCount` to limit the number of tags displayed, and the excess will be displayed as +N. You can use `showRestTagsPopover` to set whether hover +N displays Popover after maxTagCount is exceeded, the default is false. And, you can also configure Popover in the `restTagsPopoverProps` property. ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Please selection" multiple maxTagCount={1} showRestTagsPopover={true} restTagsPopoverProps={{ position: 'top' }} defaultValue={[ ['impressionism', 'visualArts', 'Monet'], ['impressionism', 'visualArts', 'Renoir'] ]} /> ); }; ``` ### Limit Tags Number In a multi-selection scene, use max to limit the number of multi-selection selections. After max is exceeded, the onExceed callback will be triggered. ```jsx live=true import React from 'react'; import { Cascader, Toast } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Please selection" multiple max={1} onExceed={v=>{ Toast.warning('exceed max'); console.log(v); }} defaultValue={[ ['impressionism', 'visualArts', 'Monet'] ]} /> ); }; ``` ### Change on Select In the case of single selection, you can also set `changeOnSelect` to allow the parent option to be selected. ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <div> <Cascader style={{ width: 400 }} treeData={treeData} changeOnSelect placeholder="Change on select" /> <br/> <br/> <Cascader style={{ width: 400 }} treeData={treeData} changeOnSelect placeholder="Searchable change on select" filterTreeNode /> </div> ); }; ``` ### Custom Display Property Set `displayProp` to select which property in the data you would like to display. By default, `label` is displayed. ```jsx live=true import React from 'react'; import { Cascader, Typography } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], } ]; return ( <> <Typography.Title heading={6}>single selection</Typography.Title> <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Please Select" displayProp='value' defaultValue={['impressionism', 'visualArts', 'Monet']} /> <br /> <br /> <Typography.Title heading={6}>multiple selection</Typography.Title> <Cascader multiple style={{ width: 300 }} treeData={treeData} defaultValue={['impressionism', 'visualArts', 'Monet']} placeholder="Please Select" displayProp='value' /> </> ); }; ``` The return format can be set by setting `displayRender`. When single selection (`multiple=false`), `displayRender((labelPath: string[]) => ReactNode)`, where labelPath is a path array composed of labels. When multiple selection (`multiple=true`), `displayRender((item: Entity, index: number) => ReactNode)`, where item is the relevant data of the node. ```typescript interface Entity { children?: Entity[]; // children list data: CascaderData; // treedata ind: number; // index key: string; // key level: number; // node level parent?: Entity; // parent data parentKey?: string; // parent key path: string[]; // key path valuePath: string[]; // value path } ``` ```jsx live=true import React from 'react'; import { Cascader, Tag, Typography } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], } ]; return ( <> <Typography.Title heading={6}>single selection</Typography.Title> <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Please select" displayRender={list => 'Selected:' + list.join(' -> ')} defaultValue={['impressionism', 'visualArts', 'Monet']} /> <br /> <br /> <Typography.Title heading={6}>multiple selection</Typography.Title> <Cascader multiple style={{ width: 300 }} treeData={treeData} defaultValue={['impressionism', 'visualArts', 'Monet']} placeholder="Please select" displayRender={(item, idx) => ( <Tag style={{ marginRight: 4 }} color='white' key={`${idx}-${item.data.label}`} > {item.data.label} </Tag> )} /> </> ); }; ``` ### Custom Separator Version: >=2.2.0 You can use `separator` to set the separator, including: the separator of the content displayed in the dropdown during search and displayed in the Trigger during single selection. ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], } ]; return ( <Cascader style={{ width: 400 }} treeData={treeData} defaultValue={['impressionism', 'visualArts', 'Monet']} filterTreeNode separator=' > ' /> ); }; ``` ### Disabled ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <div> <Cascader style={{ width: 400 }} treeData={treeData} placeholder="Please select" disabled /> <br /> <br /> <Cascader style={{ width: 400 }} treeData={treeData} placeholder="Please select" defaultValue={['impressionism', 'music', 'Debussy']} filterTreeNode disabled /> </div> ); }; ``` ### Disable Strictly You can use disableStrictly to enable strict disabling. After enabling strict disabling, when the node is disabled, the selected state cannot be changed through the relationship between the child or the parent. Take the following demo as an example, the node "Music" is strictly disabled. Therefore, when we change the selected state of its parent node "Impressionism", it will not affect the selected state of the node "Music". ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', disabled: true, children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <Cascader style={{ width: 300 }} treeData={treeData} multiple placeholder="Please select..." disableStrictly /> ); }; ``` ### the Way of Expand Menu You can use `showNext` to set the time to expand the Dropdown submenu, optional: `click` (default), `hover`. ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <Cascader style={{ width: 400 }} treeData={treeData} placeholder="Please select" showNext="hover" /> ); }; ``` ### Click to Select In multiple mode, clicking on non-leaf nodes does not trigger selection by default. You can use `clickToSelect` to enable selecting any node on click. This API is especially useful when combined with `showNext="hover"`: hovering expands the submenu, while clicking selects the current node. ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, ], }, ], } ]; return ( <Cascader style={{ width: 300 }} treeData={treeData} multiple placeholder="Please select" showNext="hover" clickToSelect /> ); }; ``` ### Additional items We have reserved slots at the top and bottom of the cascade selector. You can set them through bottomSlot or topSlot. ```jsx live=true import React from 'react'; import { Cascader, Typography } from '@douyinfe/semi-ui'; () => { const { Text } = Typography; const slotStyle = { height: '36px', display: 'flex', padding: '0 32px', alignItems: 'center', cursor: 'pointer', borderTop: '1px solid var(--semi-color-border)' }; const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Please select" bottomSlot={ <div style={slotStyle}> <Text>{`Can't find a relevant option?`}</Text> <Text link>Go to create</Text> </div> } /> ); }; ``` ### Controlled Component You can use `value` along with `onChange` property if you want to use Cascader as a controlled component. ```jsx live=true import React, { useState } from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const [value, setValue] = useState([]); const onChange = (newValue) => { setValue(newValue); }; const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], }]; return ( <Cascader style={{ width: 400 }} treeData={treeData} placeholder="Please select" value={value} onChange={onChange} /> ); }; ``` ### Auto Merge Value In the multi-selection (multiple=true) scenario, when we select the ancestor node, if we want the value not to include its corresponding descendant nodes, we can set it by `autoMergeValue`, and the default is true. When `autoMergeValue` and `leafOnly` are turned on at the same time, the latter has a higher priority. ```jsx live=true import React, { useState } from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const [value, setValue] = useState(['impressionism', 'visualArts']); const onChange = value => { setValue(value); }; const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], } ]; return ( <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Please select" value={value} multiple autoMergeValue={false} onChange={e => onChange(e)} /> ); }; ``` ### Leaf Only version: >=2.2.0 In multiple selection, you can set the value to include only leaf nodes by turning on leafOnly, that is, the displayed Tag and onChange parameter values only include value. ```jsx live=true import React, { useState } from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const [value, setValue] = useState(['impressionism', 'visualArts']); const onChange = value => { setValue(value); }; const treeData = [ { label: 'Impressionism', value: 'impressionism', children: [ { label: 'Visual Arts', value: 'visualArts', children: [ { label: 'Claude Monet', value: 'Monet', }, { label: 'Pierre-Auguste Renoir', value: 'Renoir', }, { label: 'Édouard Manet', value: 'Manet', }, ], }, { label: 'Music', value: 'music', children: [ { label: 'Claude Debussy', value: 'Debussy', }, { label: 'Maurice Ravel', value: 'Ravel', } ] } ], } ]; return ( <Cascader style={{ width: 300 }} treeData={treeData} placeholder="Please select" value={value} multiple leafOnly onChange={e => onChange(e)} /> ); }; ``` ### Checked RelationShip Version: >= 2.71.0 In multiple, `checkRelation` can be used to set the type of node selection relationship, optional: 'related' (default), 'unRelated'. When the selection relationship is 'unRelated', it means that selections between nodes do not affect each other. ```jsx live=true import React from 'react'; import { Cascader } from '@douyinfe/semi-ui'; () => { const treeData = [ { label: 'Asia', value: 'Asia', key: '0', children: [ { label: 'China', value: 'China', key: '0-0', children: [ { label: 'Beijing', value: 'Beijing', key: '0-0-0', }, { label: 'Shanghai', value: 'Shanghai', key: '0-0-1', }, ], }, ], }, { label: 'North America', value: 'North America', key: '1', } ]; return ( <Cascader multiple