How to Use the Element UI Cascader Component for Multi-Level Selection and Data Filtering
The Element UI Cascader component renders hierarchical data as nested selectable menus and supports real-time filtering, multiple selection via tags, and on-demand data loading through configurable props defined in cascader.vue and cascader-panel.vue.
The Cascader component (ElCascader) in the ElemeFE/element repository provides a complete solution for multi-level selection and data filtering in Vue.js applications. By combining a wrapper component that manages the input field and search logic with a dedicated panel component that renders nested menus, you can handle complex tree-structured data with lazy loading and custom filtering methods.
Component Architecture
The implementation splits responsibilities between two coordinated Vue components to separate UI chrome from selection logic.
ElCascader (packages/cascader/src/cascader.vue) serves as the wrapper, managing the input field, selected tags, dropdown visibility via toggleDropDownVisible(), and the filtering handler. ElCascaderPanel (packages/cascader-panel/src/cascader-panel.vue) handles the rendering of nested option menus, node state management, keyboard navigation via handleKeyDown(), and lazy loading execution.
The panel defines the DefaultProps schema that governs how each node is interpreted: value, label, children, leaf, and disabled. These field mappings allow you to adapt the component to various API data structures without transforming your dataset beforehand.
Basic Implementation
At minimum, bind an options array to the options prop and configure the props object to define which fields contain children and display labels.
<template>
<el-cascader
v-model="selected"
:options="options"
:props="cascaderProps"
placeholder="Select region">
</el-cascader>
</template>
<script>
export default {
data() {
return {
selected: [],
options: [
{
value: 'zhejiang',
label: 'Zhejiang',
children: [
{ value: 'hangzhou', label: 'Hangzhou' },
{ value: 'ningbo', label: 'Ningbo' }
]
},
{
value: 'jiangsu',
label: 'Jiangsu',
children: [
{ value: 'nanjing', label: 'Nanjing' }
]
}
],
cascaderProps: {
expandTrigger: 'click',
value: 'value',
label: 'label',
children: 'children'
}
};
}
};
</script>
Enabling Multi-Level Selection and Multiple Values
To activate multiple selection, set multiple: true inside the props configuration object. This transforms the component into a tag-based selector where users can choose multiple leaf nodes across different branches.
cascaderProps: {
multiple: true, // Enables tag-based multi-selection
emitPath: false, // Returns only leaf values instead of full path arrays
checkStrictly: false // Restricts selection to leaf nodes only when false
}
The wrapper component stores selection state in checkedValue and checkedNodes, rendering selected items as removable tags in the input field. When emitPath is true (default), the component returns an array representing the full hierarchy path; when false, it emits only the leaf node value.
Configuring Data Filtering
Enable search functionality by adding the filterable prop to ElCascader. This displays a text input that triggers a debounced filterHandler, which calls getSuggestions() (implemented around lines 444-449 in cascader.vue) to generate matching results.
By default, filtering performs a substring match against node text. Override this behavior by providing a custom filterMethod that receives the node object and keyword string:
methods: {
filterMethod(node, keyword) {
return node.label.toLowerCase().includes(keyword.toLowerCase());
}
}
<el-cascader
:options="options"
:props="cascaderProps"
:filter-method="filterMethod"
filterable>
</el-cascader>
Lazy Loading Large Hierarchies
For datasets too large to load upfront, configure lazy loading by setting lazy: true and providing a lazyLoad function in your props. The panel invokes this method (implementation spans lines 998-1035 in cascader-panel.vue) whenever a user expands a node without cached children.
cascaderProps: {
lazy: true,
lazyLoad(node, resolve) {
const { level } = node;
// Simulate API call
setTimeout(() => {
const nodes = Array.from({ length: level + 1 }).map((_, index) => ({
value: `${node.value}-${index}`,
label: `Option ${node.value}-${index}`,
leaf: level >= 2
}));
resolve(nodes);
}, 500);
}
}
The lazyLoad function receives the parent node and a resolve callback. You must call resolve with an array of child node objects matching the DefaultProps schema. Set leaf: true on nodes without further descendants to prevent expansion arrows.
Accessing Selected Node Data
Expose the underlying node objects for advanced validation or display logic by calling the public API method getCheckedNodes(leafOnly) on the Cascader instance. When leafOnly is true, the method returns only leaf nodes; when false, it includes intermediate selected nodes.
// In your component method
const nodes = this.$refs.cascader.getCheckedNodes(true);
console.log(nodes.map(n => n.label));
Summary
- Two-component architecture:
cascader.vuehandles input/filtering whilecascader-panel.vuerenders menus and manages selection state. - Configurable mapping: The
propsobject defines field names forvalue,label,children, and enables features likemultipleandemitPath. - Built-in filtering: Enable
filterablefor search support; customize matching logic viafilterMethodcalled withingetSuggestions(). - Performance optimization: Use
lazyloading with alazyLoadfunction to fetch child data on demand, implemented in the panel's store management logic.
Frequently Asked Questions
How do I enable multiple selection in the Element UI Cascader?
Set props.multiple to true in your configuration object. This activates the tag-based interface in cascader.vue, allowing users to select multiple values across different branches. The component stores selections in checkedNodes and renders them as removable tags in the input field.
Can I search and filter options across all levels of the hierarchy?
Yes. Add the filterable prop to enable the search input, which triggers the internal filterHandler. The wrapper calls getSuggestions() to filter the tree. For custom matching logic (such as case-insensitive search or pinyin matching), provide a filterMethod function that receives (node, keyword) and returns a boolean.
How does lazy loading work for large datasets?
Configure props.lazy as true and provide a lazyLoad function. When a user expands a node without cached children, the panel component calls your loader with the node and a resolve callback. Call resolve(childNodesArray) to populate the menu dynamically, as implemented in lines 998-1035 of cascader-panel.vue.
What is the difference between ElCascader and ElCascaderPanel?
ElCascader (packages/cascader/src/cascader.vue) is the high-level wrapper that manages the input box, dropdown visibility via toggleDropDownVisible(), filtering logic, and tag rendering. ElCascaderPanel (packages/cascader-panel/src/cascader-panel.vue) is the presentational component that renders the nested column menus, handles keyboard navigation, and manages the internal Store of node states.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →