Cascader
A general-purpose cascading selector.
Basic Usage
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">Default click Trigger子menu</span>
<b-cascader v-model="selected" :options="options" @change="handleChange"></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">hover Trigger子menu</span>
<b-cascader
v-model="selected"
:options="options"
:props="{ expandTrigger: 'hover' }"
@change="handleChange"
></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">option值</span>
<div class="mt-5">{{ selected }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
const selected = ref([])
function handleChange(value) {
console.log(value)
}
</script>Disabled State
Use disabled to disable the cascader.
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">Disabled项</span>
<b-cascader v-model="selected" :options="options" @change="handleChange"></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">全部Disabled</span>
<b-cascader
v-model="selected"
:options="options"
disabled
@change="handleChange"
></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">option值</span>
<div class="mt-5">{{ selected }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
disabled: true,
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
const selected = ref([])
function handleChange(value) {
console.log(value)
}
</script>Clearable
The selection can be cleared.
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<b-cascader
v-model="selected"
:options="options"
clearable
@change="handleChange"
></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<div class="mt-5">{{ selected }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
const selected = ref([])
function handleChange(value) {
console.log(value)
}
</script>Show Last Level Only
The input can be configured to show only the last level label.
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<b-cascader
v-model="selected"
:options="options"
clearable
:show-all-levels="false"
@change="handleChange"
></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<div class="mt-5">{{ selected }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
const selected = ref([])
function handleChange(value) {
console.log(value)
}
</script>Multiple Selection
Set props.multiple to enable multi-selection.
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">Default show所有tag</span>
<b-cascader
v-model="selected"
:options="options"
:props="{ multiple: true }"
@change="handleChange"
></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">collapseshowtag</span>
<b-cascader
v-model="selected"
:options="options"
:props="{ multiple: true }"
collapse-tags
@change="handleChange"
></b-cascader>
</div>
<div class="block" style="width: calc(100% - 500px); margin-right: 20px">
<span class="demonstration">option值</span>
<div class="mt-5">{{ selected }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
const selected = ref([])
function handleChange(value) {
console.log(value)
}
</script>Select Any Level
In single mode, only leaf nodes can be selected. In multi mode, checking a parent node selects its leaf nodes. Enable this feature to decouple parent-child selection and allow selecting any level.
Set props.checkStrictly = true to decouple parent-child selection, allowing independent selection at any level.
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">Single select选择任意一级option</span>
<b-cascader
v-model="selected1"
:options="options"
:props="{ checkStrictly: true }"
@change="handleChange"
></b-cascader>
<div class="mt-5">{{ selected1 }}</div>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">Multi-select选择任意一级option</span>
<b-cascader
v-model="selected2"
:options="options"
:props="{ multiple: true, checkStrictly: true }"
collapse-tags
@change="handleChange"
></b-cascader>
<div class="mt-5">{{ selected2 }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
const selected1 = ref([])
const selected2 = ref([])
function handleChange(value) {
console.log(value)
}
</script>Dynamic Loading
Dynamically load child options when a level is selected. Enable with lazy and configure the data source method via lazyload.
The lazyload method has two parameters: the first parameter node is the currently clicked node, the second resolve is the callback that must be called when data loading is complete. For more accurate display of node status, you can also mark node data with a leaf indicator (the default field is leaf, which can be modified via props.leaf). Otherwise, it simply checks whether the node has children to determine whether it is a leaf node.
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<b-cascader v-model="selected" :props="props"></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<div class="mt-5">{{ selected }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
let id = 0
const selected = ref([])
const props = {
lazy: true,
lazyLoad(node, resolve) {
const { level } = node
setTimeout(() => {
const nodes = Array.from({ length: level + 1 }).map(() => ({
value: ++id,
label: `option${id}`,
leaf: level >= 2
}))
// 通过callresolve将子节点数据返回,Noticecomponent数据Load完成
resolve(nodes)
}, 1000)
}
}
</script>Searchable
Quickly search and select options. Set filterable to true to enable search. By default, it matches options whose label (or all ancestor labels, depending on show-all-levels) contains the search text.
You can also use filter-method to customize the search logic. It accepts a function with two parameters: the node and the search keyword, and returns a boolean to indicate whether it matches.
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">Single select可Search</span>
<b-cascader
v-model="selected1"
placeholder="试试Search:鼓楼"
:options="options"
filterable
></b-cascader>
<div class="mt-5">{{ selected1 }}</div>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<span class="demonstration">Multi-select可Search</span>
<b-cascader
v-model="selected2"
placeholder="试试Search:鼓楼"
:options="options"
:props="{ multiple: true }"
collapse-tags
filterable
:filter-method="filterMethod"
></b-cascader>
<div class="mt-5">{{ selected2 }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
const selected1 = ref([])
const selected2 = ref([])
function filterMethod(node, keyword) {
return node.label.includes(keyword) && node.parent && node.parent.label === 'Xuzhou'
}
</script>Custom Options
Option content can be customized. The scoped slot receives two props: node (the current Node object) and data (the node data).
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<b-cascader :options="options">
<template #default="{ node, data }">
<span>{{ data.label }}</span>
<span v-if="!node.isLeaf">({{ data.children.length }})</span>
</template>
</b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<div class="mt-5">{{ selected }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
const selected = ref([])
function handleChange(value) {
console.log(value)
}
</script>Sizes
<template>
<div flex>
<div class="block" style="width: 220px; margin-right: 20px">
<b-cascader :options="options" size="large"></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<b-cascader :options="options"></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<b-cascader :options="options" size="small"></b-cascader>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<b-cascader :options="options" size="mini"></b-cascader>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
</script>Cascader Panel
You can use a panel display instead of the popper dialog. Usage is the same as cascader.
<template>
<div flex>
<div class="block" style="margin-right: 20px">
<b-cascader-panel v-model="selected" :options="options"></b-cascader-panel>
</div>
<div class="block" style="width: 220px; margin-right: 20px">
<div class="mt-5">{{ selected }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const options = [
{
value: 'nanjing',
label: 'Nanjing',
children: [
{
value: 'xuanwu',
label: '玄武区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'jianye',
label: '建邺区'
}
]
},
{
value: 'xuzhou',
label: 'Xuzhou',
children: [
{
value: 'tongshan',
label: '铜山区'
},
{
value: 'gulou',
label: 'Gulou District'
},
{
value: 'yunlong',
label: 'Yunlong District',
children: [
{ value: 'dalonghu', label: '大龙湖街道' },
{ value: 'guozhuanglu', label: '郭庄路街道' },
{ value: 'lvdi', label: '绿地商务城' },
{ value: 'jinlonghu', label: '金龙湖街道' }
]
},
{
value: 'jiawang',
label: 'Jiawang District'
},
{ value: 'peixian', label: '沛县' },
{ value: 'fengxian', label: '丰县' },
{ value: 'pizhou', label: '邳州City' },
{ value: 'xinyi', label: 'New沂City' }
]
}
]
const selected = ref([])
</script>Cascader Props
| Parameter | Description | Type | Options | Default |
|---|---|---|---|---|
| value / v-model | Binding value of the selected item | - | — | — |
| options | Data source for options. Key names can be configured via the Props property | array | — | — |
| props | Configuration options, see the table below | object | — | — |
| size | Size | string | medium / small / mini | — |
| placeholder | Input placeholder text | string | — | Please select |
| disabled | Disabled | boolean | — | false |
| clearable | Whether to support clearing options | boolean | — | false |
| show-all-levels | Whether to show the full path of the selected value in the input | boolean | — | true |
| collapse-tags | Whether to collapse tags in multi-select mode | boolean | - | false |
| separator | Option separator | string | — | ' / ' |
| filterable | Whether options are searchable | boolean | — | — |
| filter-method | Custom search logic. The first parameter is the node node, the second is the search keyword keyword. Returns a boolean indicating whether it matches | function(node, keyword) | - | - |
| debounce | Debounce delay for search keyword input, in milliseconds | number | — | 300 |
| before-filter | Hook before filtering. The parameter is the input value. If it returns false or a rejected Promise, filtering stops | function(value) | — | — |
| popper-class | Custom class name for the overlay | string | — | — |
Cascader Events
| Event Name | Description | Callback Parameters |
|---|---|---|
| change | Triggered when the selected node changes | Value of the selected node |
| expand-change | Triggered when the expanded node changes | Array of parent option values |
| blur | Triggered when focus is lost | (event: Event) |
| focus | Triggered when focus is gained | (event: Event) |
| visible-change | Triggered when the dropdown appears/hides | true when appearing, false when hiding |
| remove-tag | Triggered when a tag is removed in multi-select mode | Value of the node corresponding to the removed tag |
Cascader Methods
| Method Name | Description | Parameter |
|---|---|---|
| getCheckedNodes | Get the selected nodes | (leafOnly) Whether to only return leaf nodes, default is false |
Cascader Slots
| Name | Description |
|---|---|
| - | Custom content for option nodes. Parameters are { node, data }, the Node object and data of the current node respectively |
| empty | Content when no matching options are found |
CascaderPanel Attributes
| Parameter | Description | Type | Options | Default |
|---|---|---|---|---|
| value / v-model | Binding value of the selected item | - | — | — |
| options | Data source for options. Key names can be configured via the Props property | array | — | — |
| props | Configuration options, see the table below | object | — | — |
CascaderPanel Events
| Event Name | Description | Callback Parameters |
|---|---|---|
| change | Triggered when the selected node changes | Value of the selected node |
| expand-change | Triggered when the expanded node changes | Array of parent option values |
CascaderPanel Methods
| Method Name | Description | Parameter |
|---|---|---|
| getCheckedNodes | Get the array of selected nodes | (leafOnly) Whether to only return leaf nodes, default is false |
| clearCheckedNodes | Clear the selected nodes | - |
CascaderPanel Slots
| Name | Description |
|---|---|
| - | Custom content for option nodes. Parameters are { node, data }, the Node object and data of the current node respectively |
Props
| Parameter | Description | Type | Options | Default |
|---|---|---|---|---|
| expandTrigger | Trigger mode for sub-menus to expand | string | click / hover | 'click' |
| multiple | Whether to support multi-select | boolean | - | false |
| checkStrictly | Whether to strictly enforce parent-child node independence | boolean | - | false |
| emitPath | When the selected node changes, whether to return an array composed of values from each menu level where the node is located. If set to false, only the value of that node is returned | boolean | - | true |
| lazy | Whether to dynamically load child nodes. Must be used with the lazyLoad method | boolean | - | false |
| lazyLoad | Method for loading dynamic data, only effective when lazy is true | function(node, resolve), node is the currently clicked node, resolve is the callback that must be called when data loading is complete | - | - |
| value | Specifies which property of the option object to use as the option value | string | — | 'value' |
| label | Specifies which property of the option object to use as the option label | string | — | 'label' |
| children | Specifies which property of the option object to use as the option's children | string | — | 'children' |
| disabled | Specifies which property of the option object to use as the option's disabled state | string | — | 'disabled' |
| leaf | Specifies which property of the option object to use as the leaf node indicator | string | — | 'leaf' |