Cascader
LhCascader allows selecting from hierarchical data.
Basic Usage
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'
const cascaderVal = ref([])
const cascaderOpts = [
{
value: 'area',
label: 'Area',
children: [
{ value: 'beijing', label: 'Beijing' },
{ value: 'shanghai', label: 'Shanghai' },
],
},
]
</script>
<template>
<!-- Basic usage -->
<LhCascader v-model="cascaderVal" :options="cascaderOpts" placeholder="Please select" />
</template><script>
import { LhCascader } from '@lh-ui/vue3'
export default {
components: { LhCascader },
data() {
return {
cascaderVal: [],
cascaderOpts: [
{
value: 'area',
label: 'Area',
children: [
{ value: 'beijing', label: 'Beijing' },
{ value: 'shanghai', label: 'Shanghai' },
],
},
],
}
},
}
</script>
<template>
<!-- Basic usage -->
<LhCascader v-model="cascaderVal" :options="cascaderOpts" placeholder="Please select" />
</template>Type Definitions
The TypeScript type structures exported by this component (auto-extracted from packages/components/cascader/src/types.ts and @lh-ui/share/core/* sources; click each entry to expand; see the Props table above for attribute descriptions):
LhCascaderProps
export interface LhCascaderProps {
modelValue?: (string | number)[]
options?: LhCascaderNode[]
size?: LhComponentSize
disabled?: boolean
clearable?: boolean
placeholder?: string
readonly?: boolean
showAllLevels?: boolean
checkStrictly?: boolean
emitPath?: boolean
multiple?: boolean
cascading?: boolean
separator?: string
collapseTags?: boolean
filterable?: boolean
itemConfig?: LhCascaderItemConfig
sx?: LhSxProps
}LhCascaderItemConfig (from @lh-ui/share/core/cascader)
export interface LhCascaderItemConfig {
value?: string
label?: string
children?: string
disabled?: string
leaf?: string
}LhCascaderNode (from @lh-ui/share/core/cascader)
export interface LhCascaderNode {
value: string | number
label: string
disabled?: boolean
leaf?: boolean
children?: LhCascaderNode[]
}LhComponentSize (from @lh-ui/share/core/shared)
export type LhComponentSize = (typeof LH_SIZE_CONST)[keyof typeof LH_SIZE_CONST]Multi-select Mode
Enable multi-select to choose multiple results.
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'
const multiVal = ref([])
const multiOpts = [
{
value: 'zhinan',
label: 'Guide',
children: [
{ value: 'sheji', label: 'Design Guide' },
{ value: 'shejiguize', label: 'Design Rules' },
],
},
{
value: 'zujian',
label: 'Components',
children: [
{ value: 'jiben', label: 'Basic' },
{ value: 'fankui', label: 'Feedback' },
],
},
]
</script>
<template>
<!-- Multi-select mode -->
<LhCascader v-model="multiVal" :options="multiOpts" multiple />
</template><script>
import { LhCascader } from '@lh-ui/vue3'
export default {
components: { LhCascader },
data() {
return {
multiVal: [],
multiOpts: [
{
value: 'zhinan',
label: 'Guide',
children: [
{ value: 'sheji', label: 'Design Guide' },
{ value: 'shejiguize', label: 'Design Rules' },
],
},
{
value: 'zujian',
label: 'Components',
children: [
{ value: 'jiben', label: 'Basic' },
{ value: 'fankui', label: 'Feedback' },
],
},
],
}
},
}
</script>
<template>
<!-- Multi-select mode -->
<LhCascader v-model="multiVal" :options="multiOpts" multiple />
</template>Disabled Options
Disable nodes via the disabled property.
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'
const disabledVal = ref([])
const disabledOpts = [
{
value: 'zhinan',
label: 'Guide',
disabled: true,
children: [
{ value: 'sheji', label: 'Design Guide' },
],
},
{
value: 'zujian',
label: 'Components',
children: [
{ value: 'jiben', label: 'Basic' },
{ value: 'fankui', label: 'Feedback', disabled: true },
],
},
]
</script>
<template>
<!-- Disabled options -->
<LhCascader v-model="disabledVal" :options="disabledOpts" />
</template><script>
import { LhCascader } from '@lh-ui/vue3'
export default {
components: { LhCascader },
data() {
return {
disabledVal: [],
disabledOpts: [
{
value: 'zhinan',
label: 'Guide',
disabled: true,
children: [
{ value: 'sheji', label: 'Design Guide' },
],
},
{
value: 'zujian',
label: 'Components',
children: [
{ value: 'jiben', label: 'Basic' },
{ value: 'fankui', label: 'Feedback', disabled: true },
],
},
],
}
},
}
</script>
<template>
<!-- Disabled options -->
<LhCascader v-model="disabledVal" :options="disabledOpts" />
</template>Size, Disabled & Read-only
Use size to adjust the size, disabled to disable the whole selector, readonly for read-only display, placeholder for custom placeholder text, and clearable: false to hide the clear button.
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'
const enCascSize = ref([])
const enCascSize2 = ref([])
const enCascDisabled = ref([])
const enCascReadonly = ref([])
const enCascPlaceholder = ref([])
const enCascNoClear = ref([])
const enCascOpts = [
{
value: 'guide',
label: 'Guide',
children: [
{ value: 'design', label: 'Design Guide' },
{ value: 'rules', label: 'Design Rules' },
],
},
{
value: 'components',
label: 'Components',
children: [
{ value: 'basic', label: 'Basic' },
{ value: 'feedback', label: 'Feedback' },
],
},
]
</script>
<template>
<!-- small -->
<LhCascader v-model="enCascSize" :options="enCascOpts" size="small" placeholder="small" />
<!-- large -->
<LhCascader v-model="enCascSize2" :options="enCascOpts" size="large" placeholder="large" />
<!-- Disabled -->
<LhCascader v-model="enCascDisabled" :options="enCascOpts" disabled placeholder="Disabled" />
<!-- Read-only -->
<LhCascader v-model="enCascReadonly" :options="enCascOpts" readonly placeholder="Read-only" />
<!-- Custom placeholder -->
<LhCascader v-model="enCascPlaceholder" :options="enCascOpts" placeholder="Custom placeholder" />
<!-- Not clearable -->
<LhCascader v-model="enCascNoClear" :options="enCascOpts" :clearable="false" placeholder="Not clearable" />
</template><script>
import { LhCascader } from '@lh-ui/vue3'
export default {
components: { LhCascader },
data() {
return {
enCascSize: [],
enCascSize2: [],
enCascDisabled: [],
enCascReadonly: [],
enCascPlaceholder: [],
enCascNoClear: [],
enCascOpts: [
{
value: 'guide',
label: 'Guide',
children: [
{ value: 'design', label: 'Design Guide' },
{ value: 'rules', label: 'Design Rules' },
],
},
{
value: 'components',
label: 'Components',
children: [
{ value: 'basic', label: 'Basic' },
{ value: 'feedback', label: 'Feedback' },
],
},
],
}
},
}
</script>
<template>
<!-- small -->
<LhCascader v-model="enCascSize" :options="enCascOpts" size="small" placeholder="small" />
<!-- large -->
<LhCascader v-model="enCascSize2" :options="enCascOpts" size="large" placeholder="large" />
<!-- Disabled -->
<LhCascader v-model="enCascDisabled" :options="enCascOpts" disabled placeholder="Disabled" />
<!-- Read-only -->
<LhCascader v-model="enCascReadonly" :options="enCascOpts" readonly placeholder="Read-only" />
<!-- Custom placeholder -->
<LhCascader v-model="enCascPlaceholder" :options="enCascOpts" placeholder="Custom placeholder" />
<!-- Not clearable -->
<LhCascader v-model="enCascNoClear" :options="enCascOpts" :clearable="false" placeholder="Not clearable" />
</template>Path Display & Search
show-all-levelscontrols whether the input shows the full path (defaults totrue; when off only the leaf label is shown);separatorcustomizes the level separator (the search result panel honors it too);emit-path: falsebinds only the leaf value tov-model, while the input still echoes the full path;check-strictlyallows selecting nodes at any level (a click selects directly; browse children via hover expansion);filterableenables search, listing matches as full paths;collapse-tagscollapses tags in multi-select mode;cascading: falsedisables parent-child linkage in multi-select mode;item-configaliases the node fields (e.g. building the tree fromid/name), and the path echo honors it as well.
All examples below ship pre-selected values so the display differences are visible without clicking through levels: full path Zhejiang/Hangzhou/West Lake, leaf only West Lake, and Zhejiang > Hangzhou > West Lake with separator=" > ".
<script setup lang="ts">
import { ref } from 'vue'
import { LhCascader } from '@lh-ui/vue3'
const enCascFullPath = ref(['zhejiang', 'hangzhou', 'xihu'])
const enCascAllLevels = ref(['zhejiang', 'hangzhou', 'xihu'])
const enCascSep = ref(['zhejiang', 'hangzhou', 'xihu'])
const enCascEmit = ref(['xihu'])
const enCascStrict = ref(['zhejiang', 'hangzhou'])
const enCascFilter = ref([])
const enCascCollapse = ref(['xihu', 'haishu'])
const enCascLoose = ref(['xihu', 'binjiang'])
const enCascItem = ref(['zhejiang', 'hangzhou', 'xihu'])
const enPathOpts = [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{ value: 'xihu', label: 'West Lake' },
{ value: 'binjiang', label: 'Binjiang' },
],
},
{
value: 'ningbo',
label: 'Ningbo',
children: [{ value: 'haishu', label: 'Haishu' }],
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{
value: 'nanjing',
label: 'Nanjing',
children: [{ value: 'xuanwu', label: 'Xuanwu' }],
},
],
},
]
const enAliasedOpts = [
{
id: 'zhejiang',
name: 'Zhejiang',
sub: [
{
id: 'hangzhou',
name: 'Hangzhou',
sub: [
{ id: 'xihu', name: 'West Lake' },
{ id: 'binjiang', name: 'Binjiang' },
],
},
{
id: 'ningbo',
name: 'Ningbo',
sub: [{ id: 'haishu', name: 'Haishu' }],
},
],
},
]
</script>
<template>
<!-- Full path (default) -->
<LhCascader v-model="enCascFullPath" :options="enPathOpts" placeholder="Full path (default)" />
<!-- Leaf only -->
<LhCascader v-model="enCascAllLevels" :options="enPathOpts" :show-all-levels="false" placeholder="Leaf only" />
<!-- Separator > -->
<LhCascader v-model="enCascSep" :options="enPathOpts" separator=" > " placeholder="Separator >" />
<!-- Leaf value only -->
<LhCascader v-model="enCascEmit" :options="enPathOpts" :emit-path="false" placeholder="Leaf value only" />
<!-- Any level selectable -->
<LhCascader v-model="enCascStrict" :options="enPathOpts" check-strictly placeholder="Any level selectable" />
<!-- Searchable -->
<LhCascader v-model="enCascFilter" :options="enPathOpts" filterable placeholder="Searchable" />
<!-- Collapse tags -->
<LhCascader v-model="enCascCollapse" :options="enPathOpts" multiple collapse-tags placeholder="Collapse tags" />
<!-- No linkage -->
<LhCascader v-model="enCascLoose" :options="enPathOpts" multiple :cascading="false" placeholder="No linkage" />
<!-- Field aliases -->
<LhCascader v-model="enCascItem" :options="enAliasedOpts" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="Field aliases" />
</template><script>
import { LhCascader } from '@lh-ui/vue3'
export default {
components: { LhCascader },
data() {
return {
enCascFullPath: ['zhejiang', 'hangzhou', 'xihu'],
enCascAllLevels: ['zhejiang', 'hangzhou', 'xihu'],
enCascSep: ['zhejiang', 'hangzhou', 'xihu'],
enCascEmit: ['xihu'],
enCascStrict: ['zhejiang', 'hangzhou'],
enCascFilter: [],
enCascCollapse: ['xihu', 'haishu'],
enCascLoose: ['xihu', 'binjiang'],
enCascItem: ['zhejiang', 'hangzhou', 'xihu'],
enPathOpts: [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{
value: 'hangzhou',
label: 'Hangzhou',
children: [
{ value: 'xihu', label: 'West Lake' },
{ value: 'binjiang', label: 'Binjiang' },
],
},
{
value: 'ningbo',
label: 'Ningbo',
children: [{ value: 'haishu', label: 'Haishu' }],
},
],
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{
value: 'nanjing',
label: 'Nanjing',
children: [{ value: 'xuanwu', label: 'Xuanwu' }],
},
],
},
],
enAliasedOpts: [
{
id: 'zhejiang',
name: 'Zhejiang',
sub: [
{
id: 'hangzhou',
name: 'Hangzhou',
sub: [
{ id: 'xihu', name: 'West Lake' },
{ id: 'binjiang', name: 'Binjiang' },
],
},
{
id: 'ningbo',
name: 'Ningbo',
sub: [{ id: 'haishu', name: 'Haishu' }],
},
],
},
],
}
},
}
</script>
<template>
<!-- Full path (default) -->
<LhCascader v-model="enCascFullPath" :options="enPathOpts" placeholder="Full path (default)" />
<!-- Leaf only -->
<LhCascader v-model="enCascAllLevels" :options="enPathOpts" :show-all-levels="false" placeholder="Leaf only" />
<!-- Separator > -->
<LhCascader v-model="enCascSep" :options="enPathOpts" separator=" > " placeholder="Separator >" />
<!-- Leaf value only -->
<LhCascader v-model="enCascEmit" :options="enPathOpts" :emit-path="false" placeholder="Leaf value only" />
<!-- Any level selectable -->
<LhCascader v-model="enCascStrict" :options="enPathOpts" check-strictly placeholder="Any level selectable" />
<!-- Searchable -->
<LhCascader v-model="enCascFilter" :options="enPathOpts" filterable placeholder="Searchable" />
<!-- Collapse tags -->
<LhCascader v-model="enCascCollapse" :options="enPathOpts" multiple collapse-tags placeholder="Collapse tags" />
<!-- No linkage -->
<LhCascader v-model="enCascLoose" :options="enPathOpts" multiple :cascading="false" placeholder="No linkage" />
<!-- Field aliases -->
<LhCascader v-model="enCascItem" :options="enAliasedOpts" :item-config="{ value: 'id', label: 'name', children: 'sub' }" placeholder="Field aliases" />
</template>Props
| Prop | Description | Type | Default |
|---|---|---|---|
| modelValue | Bound value | (string | number)[] | () => [] |
| options | Options data | [LhCascaderNode](#type-LhCascaderNode)[] | () => [] |
| size | Size | "small" | "medium" | "large" | "mini" | "x-large" | 'medium' |
| disabled | Disabled | boolean | false |
| clearable | Clearable | boolean | true |
| placeholder | Placeholder text (falls back to the cascader.placeholder locale message when unset) | string | '' |
| readonly | Read-only | boolean | false |
| showAllLevels | Show full path in input | boolean | true |
| checkStrictly | Any level node selectable | boolean | false |
| emitPath | Return value includes full path | boolean | true |
| multiple | Multi-select | boolean | false |
| cascading | Cascading linkage | boolean | true |
| separator | Level separator | string | '/' |
| collapseTags | Collapse tags in multi-select mode | boolean | false |
| filterable | Searchable | boolean | false |
| itemConfig | — | [LhCascaderItemConfig](#type-LhCascaderItemConfig) | () => ({}) |
| sx | Shorthand layout props (e.g. { mt: 2, w: '50%' }), applied as inline styles on the trigger root element (the floating panel is not affected) | LhSxProps | — |
Events
| Event | Description | Callback |
|---|---|---|
| update:modelValue | Value changed | (value: (string | number)[]) => void |
| change | Selection changed | (value: (string | number)[], path: LhCascaderNode[] | null) => void |
Data Structure
LhCascaderNode type definition:
interface LhCascaderNode {
value: string | number
label: string
disabled?: boolean
leaf?: boolean
children?: LhCascaderNode[]
}Slots
| Slot | Description | Default |
|---|---|---|
| no-match | Custom content when the filter matches nothing | Locale message cascader.noMatch ("No matching data") |