Commit 0643460b authored by 杨奕's avatar 杨奕 Committed by baiyaaaaa

Cascader: update (#2845)

* Cascader: update

* Cascader: add tests

* Cascader: move flatOptions and add debounce
parent 3f64571f
......@@ -185,7 +185,8 @@
panel_js: 3,
panel_css: 1
};
const form = document.createElement('form');
const form = document.getElementById('fiddle-form') || document.createElement('form');
form.innerHTML = '';
const node = document.createElement('textarea');
form.method = 'post';
......@@ -197,6 +198,9 @@
node.value = data[name].toString();
form.appendChild(node.cloneNode());
}
form.setAttribute('id', 'fiddle-form');
form.style.display = 'none';
document.body.appendChild(form);
form.submit();
}
......
<script>
module.exports = {
export default {
data() {
return {
options2: [{
label: 'California',
cities: []
}, {
label: 'Florida',
cities: []
}],
props: {
value: 'label',
children: 'cities'
},
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'guide',
label: 'Guide',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'disciplines',
label: 'Disciplines',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'consistency',
label: 'Consistency'
}, {
value: 'feedback',
label: 'Feedback'
}, {
value: 'efficiency',
label: 'Efficiency'
}, {
value: 'controllability',
label: 'Controllability'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'navigation',
label: 'Navigation',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'side nav',
label: 'Side Navigation'
}, {
value: 'top nav',
label: 'Top Navigation'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'component',
label: 'Component',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}],
optionsWithDisabled: [{
value: 'zhejiang',
label: 'Zhejiang',
disabled: true,
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'layout',
label: 'Layout'
}, {
value: 'color',
label: 'Color'
}, {
value: 'typography',
label: 'Typography'
}, {
value: 'icon',
label: 'Icon'
}, {
value: 'button',
label: 'Button'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio'
}, {
value: 'checkbox',
label: 'Checkbox'
}, {
value: 'input',
label: 'Input'
}, {
value: 'input-number',
label: 'InputNumber'
}, {
value: 'select',
label: 'Select'
}, {
value: 'cascader',
label: 'Cascader'
}, {
value: 'switch',
label: 'Switch'
}, {
value: 'slider',
label: 'Slider'
}, {
value: 'time-picker',
label: 'TimePicker'
}, {
value: 'date-picker',
label: 'DatePicker'
}, {
value: 'datetime-picker',
label: 'DateTimePicker'
}, {
value: 'upload',
label: 'Upload'
}, {
value: 'rate',
label: 'Rate'
}, {
value: 'form',
label: 'Form'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table'
}, {
value: 'tag',
label: 'Tag'
}, {
value: 'progress',
label: 'Progress'
}, {
value: 'tree',
label: 'Tree'
}, {
value: 'pagination',
label: 'Pagination'
}, {
value: 'badge',
label: 'Badge'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'alert',
label: 'Alert'
}, {
value: 'loading',
label: 'Loading'
}, {
value: 'message',
label: 'Message'
}, {
value: 'message-box',
label: 'MessageBox'
}, {
value: 'notification',
label: 'Notification'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'navigation',
label: 'Navigation',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'menu',
label: 'NavMenu'
}, {
value: 'tabs',
label: 'Tabs'
}, {
value: 'breadcrumb',
label: 'Breadcrumb'
}, {
value: 'dropdown',
label: 'Dropdown'
}, {
value: 'steps',
label: 'Steps'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog'
}, {
value: 'tooltip',
label: 'Tooltip'
}, {
value: 'popover',
label: 'Popover'
}, {
value: 'card',
label: 'Card'
}, {
value: 'carousel',
label: 'Carousel'
}, {
value: 'collapse',
label: 'Collapse'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'resource',
label: 'Resource',
children: [{
value: 'nanjing',
label: 'Nanjing',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'docs',
label: 'Design Documentation'
}]
}],
optionsWithDisabled: [],
selectedOptions: [],
selectedOptions2: ['jiangsu', 'nanjing', 'zhonghuamen']
selectedOptions2: [],
selectedOptions3: ['component', 'data', 'tag']
};
},
created() {
this.optionsWithDisabled = JSON.parse(JSON.stringify(this.options));
this.optionsWithDisabled[0].disabled = true;
},
mounted() {
this.$nextTick(() => {
const demos = document.querySelectorAll('.source');
demos[0].style.padding = '0';
demos[demos.length - 1].style.padding = '0';
});
},
methods: {
handleItemChange(val) {
console.log('active item:', val);
setTimeout(_ => {
if (val.indexOf('California') > -1 && !this.options2[0].cities.length) {
this.options2[0].cities = [{
label: 'Los Angeles'
}];
} else if (val.indexOf('Florida') > -1 && !this.options2[1].cities.length) {
this.options2[1].cities = [{
label: 'Orlando'
}];
}
}, 300);
},
handleChange(value) {
console.log(value);
}
......@@ -75,67 +247,232 @@
};
</script>
<style>
.demo-cascader {
.el-cascader {
width: 222px;
}
}
.demo-cascader-size {
.el-cascader {
vertical-align: top;
margin-right: 15px;
}
}
</style>
## Cascader
It's used to select from a set of associated data set. Such as province/city/district, company level, and categories.
If the options have a clear hierarchical structure, Cascader can be used to view and select them.
### Basic usage
:::demo
There are two ways to expand child option items.
:::demo Assigning the `options` attribute to an array of options renders a Cascader. The `expand-trigger` attribute defines how child options are expanded. This example also demonstrates the `change` event, whose parameter is the value of Cascader, an array made up of the values of each selected level.
```html
<el-cascader
placeholder="Please select"
:options="options"
v-model="selectedOptions"
@change="handleChange"
></el-cascader>
<div class="block">
<span class="demonstration">Child options expand when clicked (default)</span>
<el-cascader
:options="options"
v-model="selectedOptions"
@change="handleChange">
</el-cascader>
</div>
<div class="block">
<span class="demonstration">Child options expand when hovered</span>
<el-cascader
expand-trigger="hover"
:options="options"
v-model="selectedOptions2"
@change="handleChange">
</el-cascader>
</div>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'guide',
label: 'Guide',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'disciplines',
label: 'Disciplines',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'consistency',
label: 'Consistency'
}, {
value: 'feedback',
label: 'Feedback'
}, {
value: 'efficiency',
label: 'Efficiency'
}, {
value: 'controllability',
label: 'Controllability'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'navigation',
label: 'Navigation',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'side nav',
label: 'Side Navigation'
}, {
value: 'top nav',
label: 'Top Navigation'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'component',
label: 'Component',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'layout',
label: 'Layout'
}, {
value: 'color',
label: 'Color'
}, {
value: 'typography',
label: 'Typography'
}, {
value: 'icon',
label: 'Icon'
}, {
value: 'button',
label: 'Button'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio'
}, {
value: 'checkbox',
label: 'Checkbox'
}, {
value: 'input',
label: 'Input'
}, {
value: 'input-number',
label: 'InputNumber'
}, {
value: 'select',
label: 'Select'
}, {
value: 'cascader',
label: 'Cascader'
}, {
value: 'switch',
label: 'Switch'
}, {
value: 'slider',
label: 'Slider'
}, {
value: 'time-picker',
label: 'TimePicker'
}, {
value: 'date-picker',
label: 'DatePicker'
}, {
value: 'datetime-picker',
label: 'DateTimePicker'
}, {
value: 'upload',
label: 'Upload'
}, {
value: 'rate',
label: 'Rate'
}, {
value: 'form',
label: 'Form'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table'
}, {
value: 'tag',
label: 'Tag'
}, {
value: 'progress',
label: 'Progress'
}, {
value: 'tree',
label: 'Tree'
}, {
value: 'pagination',
label: 'Pagination'
}, {
value: 'badge',
label: 'Badge'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert'
}, {
value: 'loading',
label: 'Loading'
}, {
value: 'message',
label: 'Message'
}, {
value: 'message-box',
label: 'MessageBox'
}, {
value: 'notification',
label: 'Notification'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu'
}, {
value: 'tabs',
label: 'Tabs'
}, {
value: 'breadcrumb',
label: 'Breadcrumb'
}, {
value: 'dropdown',
label: 'Dropdown'
}, {
value: 'steps',
label: 'Steps'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
value: 'dialog',
label: 'Dialog'
}, {
value: 'tooltip',
label: 'Tooltip'
}, {
value: 'popover',
label: 'Popover'
}, {
value: 'card',
label: 'Card'
}, {
value: 'carousel',
label: 'Carousel'
}, {
value: 'collapse',
label: 'Collapse'
}]
}]
}, {
value: 'resource',
label: 'Resource',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'docs',
label: 'Design Documentation'
}]
}],
selectedOptions: []
};
......@@ -152,46 +489,212 @@ It's used to select from a set of associated data set. Such as province/city/dis
### Disabled option
:::demo
Disable an option by setting a `disabled` field in the option object.
:::demo In this example, the first item in `options` array has a `disabled: true` field, so it is disabled. By default, Cascader checks the `disabled` field in each option object; if you are using another field name to indicate whether an option is disabled, you can assign it in the `props` attribute (see the API table below for details). And of course, field name `value`, `label` and `children` can also be customized in the same way.
```html
<el-cascader
placeholder="Please select"
:options="optionsWithDisabled"
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
optionsWithDisabled: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'guide',
label: 'Guide',
disabled: true,
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'disciplines',
label: 'Disciplines',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'consistency',
label: 'Consistency'
}, {
value: 'feedback',
label: 'Feedback'
}, {
value: 'efficiency',
label: 'Efficiency'
}, {
value: 'controllability',
label: 'Controllability'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'navigation',
label: 'Navigation',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'side nav',
label: 'Side Navigation'
}, {
value: 'top nav',
label: 'Top Navigation'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'component',
label: 'Component',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'layout',
label: 'Layout'
}, {
value: 'color',
label: 'Color'
}, {
value: 'typography',
label: 'Typography'
}, {
value: 'icon',
label: 'Icon'
}, {
value: 'button',
label: 'Button'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio'
}, {
value: 'checkbox',
label: 'Checkbox'
}, {
value: 'input',
label: 'Input'
}, {
value: 'input-number',
label: 'InputNumber'
}, {
value: 'select',
label: 'Select'
}, {
value: 'cascader',
label: 'Cascader'
}, {
value: 'switch',
label: 'Switch'
}, {
value: 'slider',
label: 'Slider'
}, {
value: 'time-picker',
label: 'TimePicker'
}, {
value: 'date-picker',
label: 'DatePicker'
}, {
value: 'datetime-picker',
label: 'DateTimePicker'
}, {
value: 'upload',
label: 'Upload'
}, {
value: 'rate',
label: 'Rate'
}, {
value: 'form',
label: 'Form'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table'
}, {
value: 'tag',
label: 'Tag'
}, {
value: 'progress',
label: 'Progress'
}, {
value: 'tree',
label: 'Tree'
}, {
value: 'pagination',
label: 'Pagination'
}, {
value: 'badge',
label: 'Badge'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
value: 'alert',
label: 'Alert'
}, {
value: 'loading',
label: 'Loading'
}, {
value: 'message',
label: 'Message'
}, {
value: 'message-box',
label: 'MessageBox'
}, {
value: 'notification',
label: 'Notification'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu'
}, {
value: 'tabs',
label: 'Tabs'
}, {
value: 'breadcrumb',
label: 'Breadcrumb'
}, {
value: 'dropdown',
label: 'Dropdown'
}, {
value: 'steps',
label: 'Steps'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog'
}, {
value: 'tooltip',
label: 'Tooltip'
}, {
value: 'popover',
label: 'Popover'
}, {
value: 'card',
label: 'Card'
}, {
value: 'carousel',
label: 'Carousel'
}, {
value: 'collapse',
label: 'Collapse'
}]
}]
}, {
value: 'resource',
label: 'Resource',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'docs',
label: 'Design Documentation'
}]
}]
};
}
......@@ -200,50 +703,215 @@ It's used to select from a set of associated data set. Such as province/city/dis
```
:::
### Default Value
### Display only the last level
:::demo default value is assigned by an array type value.
The input can display only the last level instead of all levels.
:::demo The `show-all-levels` attribute defines if all levels are displayed. If it is `false`, only the last level is displayed.
```html
<el-cascader
placeholder="Please select"
:options="options"
v-model="selectedOptions2"
:options="options"
:show-all-levels="false"
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'guide',
label: 'Guide',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'disciplines',
label: 'Disciplines',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'consistency',
label: 'Consistency'
}, {
value: 'feedback',
label: 'Feedback'
}, {
value: 'efficiency',
label: 'Efficiency'
}, {
value: 'controllability',
label: 'Controllability'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'navigation',
label: 'Navigation',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'side nav',
label: 'Side Navigation'
}, {
value: 'top nav',
label: 'Top Navigation'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'component',
label: 'Component',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}],
selectedOptions2: ['jiangsu', 'nanjing', 'zhonghuamen']
value: 'layout',
label: 'Layout'
}, {
value: 'color',
label: 'Color'
}, {
value: 'typography',
label: 'Typography'
}, {
value: 'icon',
label: 'Icon'
}, {
value: 'button',
label: 'Button'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio'
}, {
value: 'checkbox',
label: 'Checkbox'
}, {
value: 'input',
label: 'Input'
}, {
value: 'input-number',
label: 'InputNumber'
}, {
value: 'select',
label: 'Select'
}, {
value: 'cascader',
label: 'Cascader'
}, {
value: 'switch',
label: 'Switch'
}, {
value: 'slider',
label: 'Slider'
}, {
value: 'time-picker',
label: 'TimePicker'
}, {
value: 'date-picker',
label: 'DatePicker'
}, {
value: 'datetime-picker',
label: 'DateTimePicker'
}, {
value: 'upload',
label: 'Upload'
}, {
value: 'rate',
label: 'Rate'
}, {
value: 'form',
label: 'Form'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table'
}, {
value: 'tag',
label: 'Tag'
}, {
value: 'progress',
label: 'Progress'
}, {
value: 'tree',
label: 'Tree'
}, {
value: 'pagination',
label: 'Pagination'
}, {
value: 'badge',
label: 'Badge'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert'
}, {
value: 'loading',
label: 'Loading'
}, {
value: 'message',
label: 'Message'
}, {
value: 'message-box',
label: 'MessageBox'
}, {
value: 'notification',
label: 'Notification'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu'
}, {
value: 'tabs',
label: 'Tabs'
}, {
value: 'breadcrumb',
label: 'Breadcrumb'
}, {
value: 'dropdown',
label: 'Dropdown'
}, {
value: 'steps',
label: 'Steps'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog'
}, {
value: 'tooltip',
label: 'Tooltip'
}, {
value: 'popover',
label: 'Popover'
}, {
value: 'card',
label: 'Card'
}, {
value: 'carousel',
label: 'Carousel'
}, {
value: 'collapse',
label: 'Collapse'
}]
}]
}, {
value: 'resource',
label: 'Resource',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'docs',
label: 'Design Documentation'
}]
}]
};
}
};
......@@ -251,60 +919,214 @@ It's used to select from a set of associated data set. Such as province/city/dis
```
:::
### Size
### With default value
:::demo
:::demo The default value can be defined with an array.
```html
<div class="demo-cascader-size">
<el-cascader
placeholder="Please select"
:options="options"
size="large"
></el-cascader>
<el-cascader
placeholder="Please select"
:options="options"
></el-cascader>
<el-cascader
placeholder="Please select"
:options="options"
size="small"
></el-cascader>
</div>
<el-cascader
:options="options"
v-model="selectedOptions3"
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'guide',
label: 'Guide',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'disciplines',
label: 'Disciplines',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'consistency',
label: 'Consistency'
}, {
value: 'feedback',
label: 'Feedback'
}, {
value: 'efficiency',
label: 'Efficiency'
}, {
value: 'controllability',
label: 'Controllability'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'navigation',
label: 'Navigation',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'side nav',
label: 'Side Navigation'
}, {
value: 'top nav',
label: 'Top Navigation'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'component',
label: 'Component',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}]
value: 'layout',
label: 'Layout'
}, {
value: 'color',
label: 'Color'
}, {
value: 'typography',
label: 'Typography'
}, {
value: 'icon',
label: 'Icon'
}, {
value: 'button',
label: 'Button'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio'
}, {
value: 'checkbox',
label: 'Checkbox'
}, {
value: 'input',
label: 'Input'
}, {
value: 'input-number',
label: 'InputNumber'
}, {
value: 'select',
label: 'Select'
}, {
value: 'cascader',
label: 'Cascader'
}, {
value: 'switch',
label: 'Switch'
}, {
value: 'slider',
label: 'Slider'
}, {
value: 'time-picker',
label: 'TimePicker'
}, {
value: 'date-picker',
label: 'DatePicker'
}, {
value: 'datetime-picker',
label: 'DateTimePicker'
}, {
value: 'upload',
label: 'Upload'
}, {
value: 'rate',
label: 'Rate'
}, {
value: 'form',
label: 'Form'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table'
}, {
value: 'tag',
label: 'Tag'
}, {
value: 'progress',
label: 'Progress'
}, {
value: 'tree',
label: 'Tree'
}, {
value: 'pagination',
label: 'Pagination'
}, {
value: 'badge',
label: 'Badge'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert'
}, {
value: 'loading',
label: 'Loading'
}, {
value: 'message',
label: 'Message'
}, {
value: 'message-box',
label: 'MessageBox'
}, {
value: 'notification',
label: 'Notification'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu'
}, {
value: 'tabs',
label: 'Tabs'
}, {
value: 'breadcrumb',
label: 'Breadcrumb'
}, {
value: 'dropdown',
label: 'Dropdown'
}, {
value: 'steps',
label: 'Steps'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog'
}, {
value: 'tooltip',
label: 'Tooltip'
}, {
value: 'popover',
label: 'Popover'
}, {
value: 'card',
label: 'Card'
}, {
value: 'carousel',
label: 'Carousel'
}, {
value: 'collapse',
label: 'Collapse'
}]
}]
}, {
value: 'resource',
label: 'Resource',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'docs',
label: 'Design Documentation'
}]
}],
selectedOptions3: ['component', 'data', 'tag']
};
}
};
......@@ -312,50 +1134,214 @@ It's used to select from a set of associated data set. Such as province/city/dis
```
:::
### Hover to expand
### Change on select
Hover to expand the next level options, click to select option.
Parent options can also be selected.
:::demo
:::demo By default only the options in the last level can be selected. By assigning `change-on-select` to `true`, options in parent levels can also be selected.
```html
<el-cascader
placeholder="Please select"
:options="options"
expand-trigger="hover"
change-on-select
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'guide',
label: 'Guide',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'disciplines',
label: 'Disciplines',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'consistency',
label: 'Consistency'
}, {
value: 'feedback',
label: 'Feedback'
}, {
value: 'efficiency',
label: 'Efficiency'
}, {
value: 'controllability',
label: 'Controllability'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'navigation',
label: 'Navigation',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'side nav',
label: 'Side Navigation'
}, {
value: 'top nav',
label: 'Top Navigation'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'component',
label: 'Component',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
value: 'layout',
label: 'Layout'
}, {
value: 'color',
label: 'Color'
}, {
value: 'typography',
label: 'Typography'
}, {
value: 'icon',
label: 'Icon'
}, {
value: 'button',
label: 'Button'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio'
}, {
value: 'checkbox',
label: 'Checkbox'
}, {
value: 'input',
label: 'Input'
}, {
value: 'input-number',
label: 'InputNumber'
}, {
value: 'select',
label: 'Select'
}, {
value: 'cascader',
label: 'Cascader'
}, {
value: 'switch',
label: 'Switch'
}, {
value: 'slider',
label: 'Slider'
}, {
value: 'time-picker',
label: 'TimePicker'
}, {
value: 'date-picker',
label: 'DatePicker'
}, {
value: 'datetime-picker',
label: 'DateTimePicker'
}, {
value: 'upload',
label: 'Upload'
}, {
value: 'rate',
label: 'Rate'
}, {
value: 'form',
label: 'Form'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table'
}, {
value: 'tag',
label: 'Tag'
}, {
value: 'progress',
label: 'Progress'
}, {
value: 'tree',
label: 'Tree'
}, {
value: 'pagination',
label: 'Pagination'
}, {
value: 'badge',
label: 'Badge'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert'
}, {
value: 'loading',
label: 'Loading'
}, {
value: 'message',
label: 'Message'
}, {
value: 'message-box',
label: 'MessageBox'
}, {
value: 'notification',
label: 'Notification'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu'
}, {
value: 'tabs',
label: 'Tabs'
}, {
value: 'breadcrumb',
label: 'Breadcrumb'
}, {
value: 'dropdown',
label: 'Dropdown'
}, {
value: 'steps',
label: 'Steps'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog'
}, {
value: 'tooltip',
label: 'Tooltip'
}, {
value: 'popover',
label: 'Popover'
}, {
value: 'card',
label: 'Card'
}, {
value: 'carousel',
label: 'Carousel'
}, {
value: 'collapse',
label: 'Collapse'
}]
}]
}, {
value: 'resource',
label: 'Resource',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'docs',
label: 'Design Documentation'
}]
}]
};
}
......@@ -364,102 +1350,279 @@ Hover to expand the next level options, click to select option.
```
:::
### Change on select
### Dynamically load child options
Allow only select parent options.
Load child options when their parent option is clicked or hovered over.
:::demo
:::demo In this example, the options array does not have data of cities when initialized. With the `active-item-change` event, you can load the cities of a specific state dynamically. Besides, this example also demonstrates how `props` is used.
```html
<el-cascader
placeholder="Please select"
:options="options"
change-on-select
:options="options2"
@active-item-change="handleItemChange"
:props="props"
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
children: [{
value: 'xihu',
label: 'West Lake',
}],
}, {
value: 'ningbo',
label: 'NingBo',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
options2: [{
label: 'California',
cities: []
}, {
value: 'jiangsu',
label: 'Jiangsu',
children: [{
value: 'nanjing',
label: 'Nanjing',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}]
label: 'Florida',
cities: []
}],
props: {
value: 'label',
children: 'cities'
}
};
},
methods: {
handleItemChange(val) {
console.log('active item:', val);
setTimeout(_ => {
if (val.indexOf('California') > -1 && !this.options2[0].cities.length) {
this.options2[0].cities = [{
label: 'Los Angeles'
}];
} else if (val.indexOf('Florida') > -1 && !this.options2[1].cities.length) {
this.options2[1].cities = [{
label: 'Orlando'
}];
}
}, 300);
}
}
};
</script>
```
:::
### Search
### Filterable
Search and select options directly.
Search and select options with a keyword.
:::demo
:::demo Adding `filterable` to `el-cascader` enables filtering
```html
<el-cascader
placeholder="Please select"
:options="options"
filterable
></el-cascader>
<div class="block">
<span class="demonstration">Only options of the last level can be selected</span>
<el-cascader
placeholder="Try searching: Guide"
:options="options"
filterable
></el-cascader>
</div>
<div class="block">
<span class="demonstration">Options of all levels can be selected</span>
<el-cascader
placeholder="Try searching: Guide"
:options="options"
filterable
change-on-select
></el-cascader>
</div>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'guide',
label: 'Guide',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'disciplines',
label: 'Disciplines',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'consistency',
label: 'Consistency'
}, {
value: 'feedback',
label: 'Feedback'
}, {
value: 'efficiency',
label: 'Efficiency'
}, {
value: 'controllability',
label: 'Controllability'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'navigation',
label: 'Navigation',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'side nav',
label: 'Side Navigation'
}, {
value: 'top nav',
label: 'Top Navigation'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'component',
label: 'Component',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
value: 'layout',
label: 'Layout'
}, {
value: 'color',
label: 'Color'
}, {
value: 'typography',
label: 'Typography'
}, {
value: 'icon',
label: 'Icon'
}, {
value: 'button',
label: 'Button'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio'
}, {
value: 'checkbox',
label: 'Checkbox'
}, {
value: 'input',
label: 'Input'
}, {
value: 'input-number',
label: 'InputNumber'
}, {
value: 'select',
label: 'Select'
}, {
value: 'cascader',
label: 'Cascader'
}, {
value: 'switch',
label: 'Switch'
}, {
value: 'slider',
label: 'Slider'
}, {
value: 'time-picker',
label: 'TimePicker'
}, {
value: 'date-picker',
label: 'DatePicker'
}, {
value: 'datetime-picker',
label: 'DateTimePicker'
}, {
value: 'upload',
label: 'Upload'
}, {
value: 'rate',
label: 'Rate'
}, {
value: 'form',
label: 'Form'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table'
}, {
value: 'tag',
label: 'Tag'
}, {
value: 'progress',
label: 'Progress'
}, {
value: 'tree',
label: 'Tree'
}, {
value: 'pagination',
label: 'Pagination'
}, {
value: 'badge',
label: 'Badge'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert'
}, {
value: 'loading',
label: 'Loading'
}, {
value: 'message',
label: 'Message'
}, {
value: 'message-box',
label: 'MessageBox'
}, {
value: 'notification',
label: 'Notification'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu'
}, {
value: 'tabs',
label: 'Tabs'
}, {
value: 'breadcrumb',
label: 'Breadcrumb'
}, {
value: 'dropdown',
label: 'Dropdown'
}, {
value: 'steps',
label: 'Steps'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog'
}, {
value: 'tooltip',
label: 'Tooltip'
}, {
value: 'popover',
label: 'Popover'
}, {
value: 'card',
label: 'Card'
}, {
value: 'carousel',
label: 'Carousel'
}, {
value: 'collapse',
label: 'Collapse'
}]
}]
}, {
value: 'resource',
label: 'Resource',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'docs',
label: 'Design Documentation'
}]
}]
};
}
......@@ -471,17 +1634,30 @@ Search and select options directly.
### Attributes
| Attribute | Description | Type | Options | Default|
|---------- |-------------------- |---------|------------- |-------- |
| options | data source of the options | array | — | — |
| value | selected value | array | — | — |
| popper-class | className of popup overlay | string | — | — |
| placeholder | input placeholder | string | — | — |
| disabled | 是否禁用 | boolean | — | false |
| clearable | whether allow clear | boolean | — | false |
| expand-trigger | trigger mode of expandind the current item | string | click / hover | 'click' |
| options | data of the options | array | — | — |
| props | configuration options, see the following table | object | — | — |
| value | selected value | array | — | — |
| popper-class | custom class name for Cascader's dropdown | string | — | — |
| placeholder | input placeholder | string | — | Select |
| disabled | whether Cascader is disabled | boolean | — | false |
| clearable | whether selected value can be cleared | boolean | — | false |
| expand-trigger | trigger mode of expanding current item | string | click / hover | click |
| show-all-levels | whether to display all levels of the selected value in the input | boolean | — | true |
| filterable | whether the options can be searched | boolean | — | — |
| size | size | string | large / small / mini | — |
| debounce | debounce delay when typing filter keyword, in millisecond | number | — | 300 |
| change-on-select | whether selecting an option of any level is permitted | boolean | — | false |
| size | size of Input | string | large / small / mini | — |
### props
| Attribute | Description | Type | Accepted Values | Default |
| --------- | ----------------- | ------ | ------ | ------ |
| label | specify which key of option object is used as the option's label | string | — | — |
| value | specify which key of option object is used as the option's value | string | — | — |
| children | specify which key of option object is used as the option's child options | string | — | — |
| disabled | specify which key of option object indicates if the option is disabled | string | — | — |
### Events
| Event Name | Description | Parameters |
|---------- |-------- |---------- |
| change | triggers when the binding value changes | value |
\ No newline at end of file
| change | triggers when the binding value changes | value |
| active-item-change | triggers when active option changes, only works when `change-on-select` is `false` | an array of active options |
\ No newline at end of file
......@@ -462,7 +462,7 @@ Display options in groups.
You can filter options for your desired ones.
:::demo Adding `filterable` to `el-select` enables filtering. By default, Select will find all the options whose `label` attribute contains the input value. If you prefer other filtering strategies, you can pass the `filter-method`. `filter-method` is a `Function` that gets called when the input value changed, and its parameter is the current input value.
:::demo Adding `filterable` to `el-select` enables filtering. By default, Select will find all the options whose `label` attribute contains the input value. If you prefer other filtering strategies, you can pass the `filter-method`. `filter-method` is a `Function` that gets called when the input value changes, and its parameter is the current input value.
```html
<template>
<el-select v-model="value8" filterable placeholder="Select">
......
<script>
module.exports = {
export default {
data() {
return {
options2: [{
label: '江苏',
cities: []
}, {
label: '浙江',
cities: []
}],
props: {
value: 'label',
children: 'cities'
},
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'zhinan',
label: '指南',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'xihu',
label: 'West Lake'
value: 'yizhi',
label: '一致'
}, {
value: 'fankui',
label: '反馈'
}, {
value: 'xiaolv',
label: '效率'
}, {
value: 'kekong',
label: '可控'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'daohang',
label: '导航',
children: [{
value: 'jiangbei',
label: 'Jiang Bei'
value: 'cexiangdaohang',
label: '侧向导航'
}, {
value: 'dingbudaohang',
label: '顶部导航'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'zujian',
label: '组件',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men'
value: 'layout',
label: 'Layout 布局'
}, {
value: 'color',
label: 'Color 色彩'
}, {
value: 'typography',
label: 'Typography 字体'
}, {
value: 'icon',
label: 'Icon 图标'
}, {
value: 'button',
label: 'Button 按钮'
}]
}]
}],
optionsWithDisabled: [{
value: 'zhejiang',
label: 'Zhejiang',
disabled: true,
children: [{
value: 'hangzhou',
label: 'Hangzhou',
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio 单选框'
}, {
value: 'checkbox',
label: 'Checkbox 多选框'
}, {
value: 'input',
label: 'Input 输入框'
}, {
value: 'input-number',
label: 'InputNumber 计数器'
}, {
value: 'select',
label: 'Select 选择器'
}, {
value: 'cascader',
label: 'Cascader 级联选择器'
}, {
value: 'switch',
label: 'Switch 开关'
}, {
value: 'slider',
label: 'Slider 滑块'
}, {
value: 'time-picker',
label: 'TimePicker 时间选择器'
}, {
value: 'date-picker',
label: 'DatePicker 日期选择器'
}, {
value: 'datetime-picker',
label: 'DateTimePicker 日期时间选择器'
}, {
value: 'upload',
label: 'Upload 上传'
}, {
value: 'rate',
label: 'Rate 评分'
}, {
value: 'form',
label: 'Form 表单'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table 表格'
}, {
value: 'tag',
label: 'Tag 标签'
}, {
value: 'progress',
label: 'Progress 进度条'
}, {
value: 'tree',
label: 'Tree 树形控件'
}, {
value: 'pagination',
label: 'Pagination 分页'
}, {
value: 'badge',
label: 'Badge 标记'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert 警告'
}, {
value: 'loading',
label: 'Loading 加载'
}, {
value: 'message',
label: 'Message 消息提示'
}, {
value: 'message-box',
label: 'MessageBox 弹框'
}, {
value: 'notification',
label: 'Notification 通知'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'xihu',
label: 'West Lake'
value: 'menu',
label: 'NavMenu 导航菜单'
}, {
value: 'tabs',
label: 'Tabs 标签页'
}, {
value: 'breadcrumb',
label: 'Breadcrumb 面包屑'
}, {
value: 'dropdown',
label: 'Dropdown 下拉菜单'
}, {
value: 'steps',
label: 'Steps 步骤条'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'others',
label: 'Others',
children: [{
value: 'jiangbei',
label: 'Jiang Bei'
value: 'dialog',
label: 'Dialog 对话框'
}, {
value: 'tooltip',
label: 'Tooltip 文字提示'
}, {
value: 'popover',
label: 'Popover 弹出框'
}, {
value: 'card',
label: 'Card 卡片'
}, {
value: 'carousel',
label: 'Carousel 走马灯'
}, {
value: 'collapse',
label: 'Collapse 折叠面板'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'ziyuan',
label: '资源',
children: [{
value: 'nanjing',
label: 'Nanjing',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men'
}]
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'jiaohu',
label: '组件交互文档'
}]
}],
optionsWithDisabled: [],
selectedOptions: [],
selectedOptions2: ['jiangsu', 'nanjing', 'zhonghuamen']
selectedOptions2: [],
selectedOptions3: ['zujian', 'data', 'tag']
};
},
created() {
this.optionsWithDisabled = JSON.parse(JSON.stringify(this.options));
this.optionsWithDisabled[0].disabled = true;
},
mounted() {
this.$nextTick(() => {
const demos = document.querySelectorAll('.source');
demos[0].style.padding = '0';
demos[demos.length - 1].style.padding = '0';
});
},
methods: {
handleItemChange(val) {
console.log('active item:', val);
setTimeout(_ => {
if (val.indexOf('江苏') > -1 && !this.options2[0].cities.length) {
this.options2[0].cities = [{
label: '南京'
}];
} else if (val.indexOf('浙江') > -1 && !this.options2[1].cities.length) {
this.options2[1].cities = [{
label: '杭州'
}];
}
}, 300);
},
handleChange(value) {
console.log(value);
}
......@@ -87,57 +259,251 @@
margin-right: 15px;
}
}
.demo-cascader .block {
padding: 30px 0;
text-align: center;
border-right: solid 1px #EFF2F6;
float: left;
width: 50%;
box-sizing: border-box;
&:last-child {
border-right: none;
}
}
.demo-cascader .demonstration {
display: block;
color: #8492a6;
font-size: 14px;
margin-bottom: 20px;
}
</style>
## 级联选择
## Cascader 级联选择器
需要从一组相关联的数据集合进行选择,例如省市区,公司层级,事物分类等
当一个数据集合有清晰的层级结构时,可通过级联选择器逐级查看并选择
从一个较大的数据集合中进行选择时,用多级分类进行分隔,方便选择。
### 基础用法
### 基本使用
有两种触发子菜单的方式
:::demo
:::demo 只需为 Cascader 的`options`属性指定选项数组即可渲染出一个级联选择器。通过`expand-trigger`可以定义展开子级菜单的触发方式。本例还展示了`change`事件,它的参数为 Cascader 的绑定值:一个由各级菜单的值所组成的数组。
```html
<el-cascader
placeholder="请选择"
:options="options"
v-model="selectedOptions"
@change="handleChange"
></el-cascader>
<div class="block">
<span class="demonstration">默认 click 触发子菜单</span>
<el-cascader
:options="options"
v-model="selectedOptions"
@change="handleChange">
</el-cascader>
</div>
<div class="block">
<span class="demonstration">hover 触发子菜单</span>
<el-cascader
expand-trigger="hover"
:options="options"
v-model="selectedOptions2"
@change="handleChange">
</el-cascader>
</div>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'zhinan',
label: '指南',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'yizhi',
label: '一致'
}, {
value: 'fankui',
label: '反馈'
}, {
value: 'xiaolv',
label: '效率'
}, {
value: 'kekong',
label: '可控'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'daohang',
label: '导航',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'cexiangdaohang',
label: '侧向导航'
}, {
value: 'dingbudaohang',
label: '顶部导航'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'zujian',
label: '组件',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'layout',
label: 'Layout 布局'
}, {
value: 'color',
label: 'Color 色彩'
}, {
value: 'typography',
label: 'Typography 字体'
}, {
value: 'icon',
label: 'Icon 图标'
}, {
value: 'button',
label: 'Button 按钮'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio 单选框'
}, {
value: 'checkbox',
label: 'Checkbox 多选框'
}, {
value: 'input',
label: 'Input 输入框'
}, {
value: 'input-number',
label: 'InputNumber 计数器'
}, {
value: 'select',
label: 'Select 选择器'
}, {
value: 'cascader',
label: 'Cascader 级联选择器'
}, {
value: 'switch',
label: 'Switch 开关'
}, {
value: 'slider',
label: 'Slider 滑块'
}, {
value: 'time-picker',
label: 'TimePicker 时间选择器'
}, {
value: 'date-picker',
label: 'DatePicker 日期选择器'
}, {
value: 'datetime-picker',
label: 'DateTimePicker 日期时间选择器'
}, {
value: 'upload',
label: 'Upload 上传'
}, {
value: 'rate',
label: 'Rate 评分'
}, {
value: 'form',
label: 'Form 表单'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
value: 'table',
label: 'Table 表格'
}, {
value: 'tag',
label: 'Tag 标签'
}, {
value: 'progress',
label: 'Progress 进度条'
}, {
value: 'tree',
label: 'Tree 树形控件'
}, {
value: 'pagination',
label: 'Pagination 分页'
}, {
value: 'badge',
label: 'Badge 标记'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert 警告'
}, {
value: 'loading',
label: 'Loading 加载'
}, {
value: 'message',
label: 'Message 消息提示'
}, {
value: 'message-box',
label: 'MessageBox 弹框'
}, {
value: 'notification',
label: 'Notification 通知'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu 导航菜单'
}, {
value: 'tabs',
label: 'Tabs 标签页'
}, {
value: 'breadcrumb',
label: 'Breadcrumb 面包屑'
}, {
value: 'dropdown',
label: 'Dropdown 下拉菜单'
}, {
value: 'steps',
label: 'Steps 步骤条'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog 对话框'
}, {
value: 'tooltip',
label: 'Tooltip 文字提示'
}, {
value: 'popover',
label: 'Popover 弹出框'
}, {
value: 'card',
label: 'Card 卡片'
}, {
value: 'carousel',
label: 'Carousel 走马灯'
}, {
value: 'collapse',
label: 'Collapse 折叠面板'
}]
}]
}, {
value: 'ziyuan',
label: '资源',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'jiaohu',
label: '组件交互文档'
}]
}],
selectedOptions: []
};
......@@ -154,48 +520,212 @@
### 禁用选项
通过在数据源中设置 `disabled` 字段来声明该选项禁用的
通过在数据源中设置 `disabled` 字段来声明该选项禁用的
:::demo
:::demo 本例中,`options`指定的数组中的第一个元素含有`disabled: true`键值对,因此是禁用的。在默认情况下,Cascader 会检查数据中每一项的`disabled`字段是否为`true`,如果你的数据中表示禁用含义的字段名不为`disabled`,可以通过`props`属性来指定(详见下方 API 表格)。当然,`value``label``children`这三个字段名也可以通过同样的方式指定。
```html
<el-cascader
placeholder="请选择"
:options="optionsWithDisabled"
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
optionsWithDisabled: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'zhinan',
label: '指南',
disabled: true,
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'yizhi',
label: '一致'
}, {
value: 'fankui',
label: '反馈'
}, {
value: 'xiaolv',
label: '效率'
}, {
value: 'kekong',
label: '可控'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'daohang',
label: '导航',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'cexiangdaohang',
label: '侧向导航'
}, {
value: 'dingbudaohang',
label: '顶部导航'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'zujian',
label: '组件',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'layout',
label: 'Layout 布局'
}, {
value: 'color',
label: 'Color 色彩'
}, {
value: 'typography',
label: 'Typography 字体'
}, {
value: 'icon',
label: 'Icon 图标'
}, {
value: 'button',
label: 'Button 按钮'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio 单选框'
}, {
value: 'checkbox',
label: 'Checkbox 多选框'
}, {
value: 'input',
label: 'Input 输入框'
}, {
value: 'input-number',
label: 'InputNumber 计数器'
}, {
value: 'select',
label: 'Select 选择器'
}, {
value: 'cascader',
label: 'Cascader 级联选择器'
}, {
value: 'switch',
label: 'Switch 开关'
}, {
value: 'slider',
label: 'Slider 滑块'
}, {
value: 'time-picker',
label: 'TimePicker 时间选择器'
}, {
value: 'date-picker',
label: 'DatePicker 日期选择器'
}, {
value: 'datetime-picker',
label: 'DateTimePicker 日期时间选择器'
}, {
value: 'upload',
label: 'Upload 上传'
}, {
value: 'rate',
label: 'Rate 评分'
}, {
value: 'form',
label: 'Form 表单'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table 表格'
}, {
value: 'tag',
label: 'Tag 标签'
}, {
value: 'progress',
label: 'Progress 进度条'
}, {
value: 'tree',
label: 'Tree 树形控件'
}, {
value: 'pagination',
label: 'Pagination 分页'
}, {
value: 'badge',
label: 'Badge 标记'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert 警告'
}, {
value: 'loading',
label: 'Loading 加载'
}, {
value: 'message',
label: 'Message 消息提示'
}, {
value: 'message-box',
label: 'MessageBox 弹框'
}, {
value: 'notification',
label: 'Notification 通知'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu 导航菜单'
}, {
value: 'tabs',
label: 'Tabs 标签页'
}, {
value: 'breadcrumb',
label: 'Breadcrumb 面包屑'
}, {
value: 'dropdown',
label: 'Dropdown 下拉菜单'
}, {
value: 'steps',
label: 'Steps 步骤条'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
value: 'dialog',
label: 'Dialog 对话框'
}, {
value: 'tooltip',
label: 'Tooltip 文字提示'
}, {
value: 'popover',
label: 'Popover 弹出框'
}, {
value: 'card',
label: 'Card 卡片'
}, {
value: 'carousel',
label: 'Carousel 走马灯'
}, {
value: 'collapse',
label: 'Collapse 折叠面板'
}]
}]
}, {
value: 'ziyuan',
label: '资源',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'jiaohu',
label: '组件交互文档'
}]
}]
};
}
......@@ -204,50 +734,215 @@
```
:::
### 默认值
### 仅显示最后一级
:::demo 默认值通过数组的方式指定。
可以仅在输入框中显示选中项最后一级的标签,而不是选中项所在的完整路径。
:::demo 属性`show-all-levels`定义了是否显示完整的路径,将其赋值为`false`则仅显示最后一级
```html
<el-cascader
placeholder="请选择"
:options="options"
v-model="selectedOptions2"
:show-all-levels="false"
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'zhinan',
label: '指南',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'yizhi',
label: '一致'
}, {
value: 'fankui',
label: '反馈'
}, {
value: 'xiaolv',
label: '效率'
}, {
value: 'kekong',
label: '可控'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'daohang',
label: '导航',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'cexiangdaohang',
label: '侧向导航'
}, {
value: 'dingbudaohang',
label: '顶部导航'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'zujian',
label: '组件',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}],
selectedOptions2: ['jiangsu', 'nanjing', 'zhonghuamen']
value: 'layout',
label: 'Layout 布局'
}, {
value: 'color',
label: 'Color 色彩'
}, {
value: 'typography',
label: 'Typography 字体'
}, {
value: 'icon',
label: 'Icon 图标'
}, {
value: 'button',
label: 'Button 按钮'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio 单选框'
}, {
value: 'checkbox',
label: 'Checkbox 多选框'
}, {
value: 'input',
label: 'Input 输入框'
}, {
value: 'input-number',
label: 'InputNumber 计数器'
}, {
value: 'select',
label: 'Select 选择器'
}, {
value: 'cascader',
label: 'Cascader 级联选择器'
}, {
value: 'switch',
label: 'Switch 开关'
}, {
value: 'slider',
label: 'Slider 滑块'
}, {
value: 'time-picker',
label: 'TimePicker 时间选择器'
}, {
value: 'date-picker',
label: 'DatePicker 日期选择器'
}, {
value: 'datetime-picker',
label: 'DateTimePicker 日期时间选择器'
}, {
value: 'upload',
label: 'Upload 上传'
}, {
value: 'rate',
label: 'Rate 评分'
}, {
value: 'form',
label: 'Form 表单'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table 表格'
}, {
value: 'tag',
label: 'Tag 标签'
}, {
value: 'progress',
label: 'Progress 进度条'
}, {
value: 'tree',
label: 'Tree 树形控件'
}, {
value: 'pagination',
label: 'Pagination 分页'
}, {
value: 'badge',
label: 'Badge 标记'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert 警告'
}, {
value: 'loading',
label: 'Loading 加载'
}, {
value: 'message',
label: 'Message 消息提示'
}, {
value: 'message-box',
label: 'MessageBox 弹框'
}, {
value: 'notification',
label: 'Notification 通知'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu 导航菜单'
}, {
value: 'tabs',
label: 'Tabs 标签页'
}, {
value: 'breadcrumb',
label: 'Breadcrumb 面包屑'
}, {
value: 'dropdown',
label: 'Dropdown 下拉菜单'
}, {
value: 'steps',
label: 'Steps 步骤条'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog 对话框'
}, {
value: 'tooltip',
label: 'Tooltip 文字提示'
}, {
value: 'popover',
label: 'Popover 弹出框'
}, {
value: 'card',
label: 'Card 卡片'
}, {
value: 'carousel',
label: 'Carousel 走马灯'
}, {
value: 'collapse',
label: 'Collapse 折叠面板'
}]
}]
}, {
value: 'ziyuan',
label: '资源',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'jiaohu',
label: '组件交互文档'
}]
}]
};
}
};
......@@ -255,60 +950,214 @@
```
:::
### 尺寸
### 默认值
:::demo 提供三种尺寸的级联选择器
:::demo 默认值通过数组的方式指定。
```html
<div class="demo-cascader-size">
<el-cascader
placeholder="请选择"
:options="options"
size="large"
></el-cascader>
<el-cascader
placeholder="请选择"
:options="options"
></el-cascader>
<el-cascader
placeholder="请选择"
:options="options"
size="small"
></el-cascader>
</div>
<el-cascader
:options="options"
v-model="selectedOptions3"
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'zhinan',
label: '指南',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'yizhi',
label: '一致'
}, {
value: 'fankui',
label: '反馈'
}, {
value: 'xiaolv',
label: '效率'
}, {
value: 'kekong',
label: '可控'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'daohang',
label: '导航',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'cexiangdaohang',
label: '侧向导航'
}, {
value: 'dingbudaohang',
label: '顶部导航'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'zujian',
label: '组件',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}]
value: 'layout',
label: 'Layout 布局'
}, {
value: 'color',
label: 'Color 色彩'
}, {
value: 'typography',
label: 'Typography 字体'
}, {
value: 'icon',
label: 'Icon 图标'
}, {
value: 'button',
label: 'Button 按钮'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio 单选框'
}, {
value: 'checkbox',
label: 'Checkbox 多选框'
}, {
value: 'input',
label: 'Input 输入框'
}, {
value: 'input-number',
label: 'InputNumber 计数器'
}, {
value: 'select',
label: 'Select 选择器'
}, {
value: 'cascader',
label: 'Cascader 级联选择器'
}, {
value: 'switch',
label: 'Switch 开关'
}, {
value: 'slider',
label: 'Slider 滑块'
}, {
value: 'time-picker',
label: 'TimePicker 时间选择器'
}, {
value: 'date-picker',
label: 'DatePicker 日期选择器'
}, {
value: 'datetime-picker',
label: 'DateTimePicker 日期时间选择器'
}, {
value: 'upload',
label: 'Upload 上传'
}, {
value: 'rate',
label: 'Rate 评分'
}, {
value: 'form',
label: 'Form 表单'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table 表格'
}, {
value: 'tag',
label: 'Tag 标签'
}, {
value: 'progress',
label: 'Progress 进度条'
}, {
value: 'tree',
label: 'Tree 树形控件'
}, {
value: 'pagination',
label: 'Pagination 分页'
}, {
value: 'badge',
label: 'Badge 标记'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert 警告'
}, {
value: 'loading',
label: 'Loading 加载'
}, {
value: 'message',
label: 'Message 消息提示'
}, {
value: 'message-box',
label: 'MessageBox 弹框'
}, {
value: 'notification',
label: 'Notification 通知'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu 导航菜单'
}, {
value: 'tabs',
label: 'Tabs 标签页'
}, {
value: 'breadcrumb',
label: 'Breadcrumb 面包屑'
}, {
value: 'dropdown',
label: 'Dropdown 下拉菜单'
}, {
value: 'steps',
label: 'Steps 步骤条'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog 对话框'
}, {
value: 'tooltip',
label: 'Tooltip 文字提示'
}, {
value: 'popover',
label: 'Popover 弹出框'
}, {
value: 'card',
label: 'Card 卡片'
}, {
value: 'carousel',
label: 'Carousel 走马灯'
}, {
value: 'collapse',
label: 'Collapse 折叠面板'
}]
}]
}, {
value: 'ziyuan',
label: '资源',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'jiaohu',
label: '组件交互文档'
}]
}],
selectedOptions3: ['zujian', 'data', 'tag']
};
}
};
......@@ -316,50 +1165,214 @@
```
:::
### 移入展开
### 选择即改变
在鼠标移入时就展开下级菜单,完成选择仍需要进行点击
点击或移入选项即表示选中该项,可用于选择任意一级菜单的选项
:::demo
:::demo 若需要允许用户选择任意一级选项,则可将`change-on-select`赋值为`true`
```html
<el-cascader
placeholder="请选择"
:options="options"
expand-trigger="hover"
change-on-select
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'zhinan',
label: '指南',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'yizhi',
label: '一致'
}, {
value: 'fankui',
label: '反馈'
}, {
value: 'xiaolv',
label: '效率'
}, {
value: 'kekong',
label: '可控'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'daohang',
label: '导航',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'cexiangdaohang',
label: '侧向导航'
}, {
value: 'dingbudaohang',
label: '顶部导航'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'zujian',
label: '组件',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'layout',
label: 'Layout 布局'
}, {
value: 'color',
label: 'Color 色彩'
}, {
value: 'typography',
label: 'Typography 字体'
}, {
value: 'icon',
label: 'Icon 图标'
}, {
value: 'button',
label: 'Button 按钮'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio 单选框'
}, {
value: 'checkbox',
label: 'Checkbox 多选框'
}, {
value: 'input',
label: 'Input 输入框'
}, {
value: 'input-number',
label: 'InputNumber 计数器'
}, {
value: 'select',
label: 'Select 选择器'
}, {
value: 'cascader',
label: 'Cascader 级联选择器'
}, {
value: 'switch',
label: 'Switch 开关'
}, {
value: 'slider',
label: 'Slider 滑块'
}, {
value: 'time-picker',
label: 'TimePicker 时间选择器'
}, {
value: 'date-picker',
label: 'DatePicker 日期选择器'
}, {
value: 'datetime-picker',
label: 'DateTimePicker 日期时间选择器'
}, {
value: 'upload',
label: 'Upload 上传'
}, {
value: 'rate',
label: 'Rate 评分'
}, {
value: 'form',
label: 'Form 表单'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
value: 'table',
label: 'Table 表格'
}, {
value: 'tag',
label: 'Tag 标签'
}, {
value: 'progress',
label: 'Progress 进度条'
}, {
value: 'tree',
label: 'Tree 树形控件'
}, {
value: 'pagination',
label: 'Pagination 分页'
}, {
value: 'badge',
label: 'Badge 标记'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert 警告'
}, {
value: 'loading',
label: 'Loading 加载'
}, {
value: 'message',
label: 'Message 消息提示'
}, {
value: 'message-box',
label: 'MessageBox 弹框'
}, {
value: 'notification',
label: 'Notification 通知'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu 导航菜单'
}, {
value: 'tabs',
label: 'Tabs 标签页'
}, {
value: 'breadcrumb',
label: 'Breadcrumb 面包屑'
}, {
value: 'dropdown',
label: 'Dropdown 下拉菜单'
}, {
value: 'steps',
label: 'Steps 步骤条'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog 对话框'
}, {
value: 'tooltip',
label: 'Tooltip 文字提示'
}, {
value: 'popover',
label: 'Popover 弹出框'
}, {
value: 'card',
label: 'Card 卡片'
}, {
value: 'carousel',
label: 'Carousel 走马灯'
}, {
value: 'collapse',
label: 'Collapse 折叠面板'
}]
}]
}, {
value: 'ziyuan',
label: '资源',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'jiaohu',
label: '组件交互文档'
}]
}]
};
}
......@@ -368,52 +1381,51 @@
```
:::
### 选择即改变
### 动态加载次级选项
该模式下允许只选中父级选项。
当选中某一级时,动态加载该级下的选项。
:::demo
:::demo 本例的选项数据源在初始化时不包含城市数据。利用`active-item-change`事件,可以在用户点击某个省份时拉取该省份下的城市数据。此外,本例还展示了`props`属性的用法。
```html
<el-cascader
placeholder="请选择"
:options="options"
change-on-select
:options="options2"
@active-item-change="handleItemChange"
:props="props"
></el-cascader>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
children: [{
value: 'xihu',
label: 'West Lake',
}],
}, {
value: 'ningbo',
label: 'NingBo',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
options2: [{
label: '江苏',
cities: []
}, {
value: 'jiangsu',
label: 'Jiangsu',
children: [{
value: 'nanjing',
label: 'Nanjing',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
}]
label: '浙江',
cities: []
}],
props: {
value: 'label',
children: 'cities'
}
};
},
methods: {
handleItemChange(val) {
console.log('active item:', val);
setTimeout(_ => {
if (val.indexOf('江苏') > -1 && !this.options2[0].cities.length) {
this.options2[0].cities = [{
label: '南京'
}];
} else if (val.indexOf('浙江') > -1 && !this.options2[1].cities.length) {
this.options2[1].cities = [{
label: '杭州'
}];
}
}, 300);
}
}
};
</script>
......@@ -422,48 +1434,226 @@
### 可搜索
可以直接搜索选项并选择。
可以快捷地搜索选项并选择。
:::demo
:::demo`filterable`赋值为`true`即可打开搜索功能。
```html
<el-cascader
placeholder="请选择"
:options="options"
filterable
></el-cascader>
<div class="block">
<span class="demonstration">只可选择最后一级菜单的选项</span>
<el-cascader
placeholder="试试搜索:指南"
:options="options"
filterable
></el-cascader>
</div>
<div class="block">
<span class="demonstration">可选择任意一级菜单的选项</span>
<el-cascader
placeholder="试试搜索:指南"
:options="options"
filterable
change-on-select
></el-cascader>
</div>
<script>
module.exports = {
export default {
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
value: 'zhinan',
label: '指南',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'xihu',
label: 'West Lake',
}],
value: 'yizhi',
label: '一致'
}, {
value: 'fankui',
label: '反馈'
}, {
value: 'xiaolv',
label: '效率'
}, {
value: 'kekong',
label: '可控'
}]
}, {
value: 'ningbo',
label: 'NingBo',
value: 'daohang',
label: '导航',
children: [{
value: 'jiangbei',
label: 'Jiang Bei',
}],
}],
value: 'cexiangdaohang',
label: '侧向导航'
}, {
value: 'dingbudaohang',
label: '顶部导航'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
value: 'zujian',
label: '组件',
children: [{
value: 'nanjing',
label: 'Nanjing',
value: 'basic',
label: 'Basic',
children: [{
value: 'layout',
label: 'Layout 布局'
}, {
value: 'color',
label: 'Color 色彩'
}, {
value: 'typography',
label: 'Typography 字体'
}, {
value: 'icon',
label: 'Icon 图标'
}, {
value: 'button',
label: 'Button 按钮'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio 单选框'
}, {
value: 'checkbox',
label: 'Checkbox 多选框'
}, {
value: 'input',
label: 'Input 输入框'
}, {
value: 'input-number',
label: 'InputNumber 计数器'
}, {
value: 'select',
label: 'Select 选择器'
}, {
value: 'cascader',
label: 'Cascader 级联选择器'
}, {
value: 'switch',
label: 'Switch 开关'
}, {
value: 'slider',
label: 'Slider 滑块'
}, {
value: 'time-picker',
label: 'TimePicker 时间选择器'
}, {
value: 'date-picker',
label: 'DatePicker 日期选择器'
}, {
value: 'datetime-picker',
label: 'DateTimePicker 日期时间选择器'
}, {
value: 'upload',
label: 'Upload 上传'
}, {
value: 'rate',
label: 'Rate 评分'
}, {
value: 'form',
label: 'Form 表单'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table 表格'
}, {
value: 'tag',
label: 'Tag 标签'
}, {
value: 'progress',
label: 'Progress 进度条'
}, {
value: 'tree',
label: 'Tree 树形控件'
}, {
value: 'pagination',
label: 'Pagination 分页'
}, {
value: 'badge',
label: 'Badge 标记'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert 警告'
}, {
value: 'loading',
label: 'Loading 加载'
}, {
value: 'message',
label: 'Message 消息提示'
}, {
value: 'message-box',
label: 'MessageBox 弹框'
}, {
value: 'notification',
label: 'Notification 通知'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men',
}],
}],
value: 'menu',
label: 'NavMenu 导航菜单'
}, {
value: 'tabs',
label: 'Tabs 标签页'
}, {
value: 'breadcrumb',
label: 'Breadcrumb 面包屑'
}, {
value: 'dropdown',
label: 'Dropdown 下拉菜单'
}, {
value: 'steps',
label: 'Steps 步骤条'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog 对话框'
}, {
value: 'tooltip',
label: 'Tooltip 文字提示'
}, {
value: 'popover',
label: 'Popover 弹出框'
}, {
value: 'card',
label: 'Card 卡片'
}, {
value: 'carousel',
label: 'Carousel 走马灯'
}, {
value: 'collapse',
label: 'Collapse 折叠面板'
}]
}]
}, {
value: 'ziyuan',
label: '资源',
children: [{
value: 'axure',
label: 'Axure Components'
}, {
value: 'sketch',
label: 'Sketch Templates'
}, {
value: 'jiaohu',
label: '组件交互文档'
}]
}]
};
}
......@@ -475,17 +1665,30 @@
### Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|---------- |-------- |---------- |------------- |-------- |
| options | 可选项数据源 | array | — | — |
| value | 指定选中项 | array | — | — |
| popper-class | 自定义浮层类名 | string | — | — |
| placeholder | 输入框占位文本 | string | — | — |
| disabled | 是否禁用 | boolean | — | false |
| clearable | 是否支持清除 | boolean | — | false |
| expand-trigger | 次级菜单的展开方式 | string | click / hover | 'click' |
| filterable | 是否支持搜索选项 | boolean | — | — |
| size | 尺寸 | string | large / small / mini | — |
| options | 可选项数据源,键名可通过 `props` 属性配置 | array | — | — |
| props | 配置选项,具体见下表 | object | — | — |
| value | 选中项绑定值 | array | — | — |
| popper-class | 自定义浮层类名 | string | — | — |
| placeholder | 输入框占位文本 | string | — | 请选择 |
| disabled | 是否禁用 | boolean | — | false |
| clearable | 是否支持清空选项 | boolean | — | false |
| expand-trigger | 次级菜单的展开方式 | string | click / hover | click |
| show-all-levels | 输入框中是否显示选中值的完整路径 | boolean | — | true |
| filterable | 是否可搜索选项 | boolean | — | — |
| debounce | 搜索关键词输入的去抖延迟,毫秒 | number | — | 300 |
| change-on-select | 是否允许选择任意一级的选项 | boolean | — | false |
| size | 尺寸 | string | large / small / mini | — |
### props
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
| -------- | ----------------- | ------ | ------ | ------ |
| value | 指定选项的值为选项对象的某个属性值 | string | — | — |
| label | 指定选项标签为选项对象的某个属性值 | string | — | — |
| children | 指定选项的子选项为选项对象的某个属性值 | string | — | — |
| disabled | 指定选项的禁用为选项对象的某个属性值 | string | — | — |
### Events
| 事件名称 | 说明 | 回调参数 |
|---------- |-------- |---------- |
| change | 当绑定值变化时触发的事件 | 当前值 |
\ No newline at end of file
| change | 当绑定值变化时触发的事件 | 当前值 |
| active-item-change | 当父级选项变化时触发的事件,仅在 `change-on-select``false` 时可用 | 各父级选项组成的数组 |
\ No newline at end of file
require('offline-plugin/runtime').install();
process.env.NODE_ENV === 'production' && require('offline-plugin/runtime').install();
import Vue from 'vue';
import entry from './app';
......
......@@ -78,7 +78,7 @@
},
{
"path": "/cascader",
"title": "Cascader 级联选择"
"title": "Cascader 级联选择"
},
{
"path": "/switch",
......
......@@ -17,9 +17,9 @@
<el-input
ref="input"
:readonly="!filterable"
:placeholder="displayValue ? undefined : placeholder"
:placeholder="currentLabels.length ? undefined : placeholder"
v-model="inputValue"
@change="handleInputChange"
@change="debouncedInputChange"
:validate-event="false"
:size="size"
:disabled="disabled"
......@@ -27,7 +27,7 @@
<template slot="icon">
<i
key="1"
v-if="inputHover && displayValue !== ''"
v-if="clearable && inputHover && currentLabels.length"
class="el-input__icon el-icon-circle-close el-cascader__clearIcon"
@click="clearValue"
></i>
......@@ -39,7 +39,17 @@
></i>
</template>
</el-input>
<span class="el-cascader__label" v-show="inputValue === ''">{{displayValue}}</span>
<span class="el-cascader__label" v-show="inputValue === ''">
<template v-if="showAllLevels">
<template v-for="(label, index) in currentLabels">
{{ label }}
<span v-if="index < currentLabels.length - 1"> / </span>
</template>
</template>
<template v-else>
{{ currentLabels[currentLabels.length - 1] }}
</template>
</span>
</span>
</template>
......@@ -51,6 +61,8 @@ import Popper from 'element-ui/src/utils/vue-popper';
import Clickoutside from 'element-ui/src/utils/clickoutside';
import emitter from 'element-ui/src/mixins/emitter';
import Locale from 'element-ui/src/mixins/locale';
import { t } from 'element-ui/src/locale';
import debounce from 'throttle-debounce/debounce';
const popperMixin = {
props: {
......@@ -84,17 +96,33 @@ export default {
type: Array,
required: true
},
props: {
type: Object,
default() {
return {
children: 'children',
label: 'label',
value: 'value',
disabled: 'disabled'
};
}
},
value: {
type: Array,
default() {
return [];
}
},
placeholder: String,
placeholder: {
type: String,
default() {
return t('el.cascader.placeholder');
}
},
disabled: Boolean,
clearable: {
type: Boolean,
default: true
default: false
},
changeOnSelect: Boolean,
popperClass: String,
......@@ -103,20 +131,53 @@ export default {
default: 'click'
},
filterable: Boolean,
size: String
size: String,
showAllLevels: {
type: Boolean,
default: true
},
debounce: {
type: Number,
default: 300
}
},
data() {
return {
currentValue: this.value,
displayValue: this.value.join('/'),
menu: null,
debouncedInputChange() {},
menuVisible: false,
inputHover: false,
inputValue: '',
flatOptions: this.filterable && this.flattenOptions(this.options)
flatOptions: null
};
},
computed: {
labelKey() {
return this.props.label || 'label';
},
valueKey() {
return this.props.value || 'value';
},
childrenKey() {
return this.props.children || 'children';
},
currentLabels() {
let options = this.options;
let labels = [];
this.currentValue.forEach(value => {
const targetOption = options && options.filter(option => option[this.valueKey] === value)[0];
if (targetOption) {
labels.push(targetOption[this.labelKey]);
options = targetOption[this.childrenKey];
}
});
return labels;
}
},
watch: {
menuVisible(value) {
value ? this.showMenu() : this.hideMenu();
......@@ -125,29 +186,40 @@ export default {
this.currentValue = value;
},
currentValue(value) {
this.displayValue = value.join('/');
this.dispatch('ElFormItem', 'el.form.change', [value]);
},
options(value) {
this.menu.options = value;
options: {
deep: true,
handler(value) {
if (!this.menu) {
this.initMenu();
}
this.flatOptions = this.flattenOptions(this.options);
this.menu.options = value;
}
}
},
methods: {
initMenu() {
this.menu = new Vue(ElCascaderMenu).$mount();
this.menu.options = this.options;
this.menu.props = this.props;
this.menu.expandTrigger = this.expandTrigger;
this.menu.changeOnSelect = this.changeOnSelect;
this.menu.popperClass = this.popperClass;
this.popperElm = this.menu.$el;
this.menu.$on('pick', this.handlePick);
this.menu.$on('activeItemChange', this.handleActiveItemChange);
},
showMenu() {
if (!this.menu) {
this.menu = new Vue(ElCascaderMenu).$mount();
this.menu.options = this.options;
this.menu.expandTrigger = this.expandTrigger;
this.menu.changeOnSelect = this.changeOnSelect;
this.menu.popperClass = this.popperClass;
this.popperElm = this.menu.$el;
this.initMenu();
}
this.menu.value = this.currentValue.slice(0);
this.menu.visible = true;
this.menu.options = this.options;
this.menu.$on('pick', this.handlePick);
this.updatePopper();
this.$nextTick(_ => {
this.menu.inputWidth = this.$refs.input.$el.offsetWidth - 2;
......@@ -157,6 +229,12 @@ export default {
this.inputValue = '';
this.menu.visible = false;
},
handleActiveItemChange(value) {
this.$nextTick(_ => {
this.updatePopper();
});
this.$emit('active-item-change', value);
},
handlePick(value, close = true) {
this.currentValue = value;
this.$emit('input', value);
......@@ -176,14 +254,14 @@ export default {
}
let filteredFlatOptions = flatOptions.filter(optionsStack => {
return optionsStack.some(option => option.label.indexOf(value) > -1);
return optionsStack.some(option => new RegExp(value, 'i').test(option[this.labelKey]));
});
if (filteredFlatOptions.length > 0) {
filteredFlatOptions = filteredFlatOptions.map(optionStack => {
return {
__IS__FLAT__OPTIONS: true,
value: optionStack.map(item => item.value),
value: optionStack.map(item => item[this.valueKey]),
label: this.renderFilteredOptionLabel(value, optionStack)
};
});
......@@ -198,8 +276,11 @@ export default {
this.menu.options = filteredFlatOptions;
},
renderFilteredOptionLabel(inputValue, optionsStack) {
return optionsStack.map(({ label }, index) => {
const node = label.indexOf(inputValue) > -1 ? this.highlightKeyword(label, inputValue) : label;
return optionsStack.map((option, index) => {
const label = option[this.labelKey];
const keywordIndex = label.toLowerCase().indexOf(inputValue.toLowerCase());
const labelPart = label.slice(keywordIndex, inputValue.length + keywordIndex);
const node = keywordIndex > -1 ? this.highlightKeyword(label, labelPart) : label;
return index === 0 ? node : [' / ', node];
});
},
......@@ -215,10 +296,13 @@ export default {
let flatOptions = [];
options.forEach((option) => {
const optionsStack = ancestor.concat(option);
if (!option.children) {
if (!option[this.childrenKey]) {
flatOptions.push(optionsStack);
} else {
flatOptions = flatOptions.concat(this.flattenOptions(option.children, optionsStack));
if (this.changeOnSelect) {
flatOptions.push(optionsStack);
}
flatOptions = flatOptions.concat(this.flattenOptions(option[this.childrenKey], optionsStack));
}
});
return flatOptions;
......@@ -238,6 +322,16 @@ export default {
}
this.menuVisible = !this.menuVisible;
}
},
created() {
this.debouncedInputChange = debounce(this.debounce, value => {
this.handleInputChange(value);
});
},
mounted() {
this.flatOptions = this.flattenOptions(this.options);
}
};
</script>
......@@ -6,6 +6,7 @@
return {
inputWidth: 0,
options: [],
props: {},
visible: false,
activeValue: [],
value: [],
......@@ -34,6 +35,20 @@
cache: false,
get() {
const activeValue = this.activeValue;
const configurableProps = ['label', 'value', 'children', 'disabled'];
const formatOptions = options => {
options.forEach(option => {
if (option.__IS__FLAT__OPTIONS) return;
configurableProps.forEach(prop => {
const value = option[this.props[prop] || prop];
if (value) option[prop] = value;
});
if (Array.isArray(option.children)) {
formatOptions(option.children);
}
});
};
const loadActiveOptions = (options, activeOptions = []) => {
const level = activeOptions.length;
......@@ -48,6 +63,7 @@
return activeOptions;
};
formatOptions(this.options);
return loadActiveOptions(this.options);
}
}
......@@ -66,7 +82,11 @@
const len = this.activeOptions.length;
this.activeValue.splice(menuIndex, len, item.value);
this.activeOptions.splice(menuIndex + 1, len, item.children);
if (this.changeOnSelect) this.$emit('pick', this.activeValue, false);
if (this.changeOnSelect) {
this.$emit('pick', this.activeValue, false);
} else {
this.$emit('activeItemChange', this.activeValue);
}
}
},
......@@ -116,7 +136,7 @@
});
let menuStyle = {};
if (isFlat) {
menuStyle.width = this.inputWidth + 'px';
menuStyle.minWidth = this.inputWidth + 'px';
}
return (
......
......@@ -13,7 +13,7 @@
.el-input__inner {
cursor: pointer;
background-color: transparent;
z-index: 1;
z-index: var(--index-normal);
}
.el-input__icon {
......@@ -34,7 +34,7 @@
top: 0;
height: 100%;
line-height: 34px;
padding: 0 15px 0 10px;
padding: 0 25px 0 10px;
color: var(--input-color);
width: 100%;
white-space: nowrap;
......@@ -42,6 +42,11 @@
overflow: hidden;
box-sizing: border-box;
cursor: pointer;
font-size: 14px;
text-align: left;
span {
color: var(--color-light-silver);
}
}
@m large {
......@@ -65,24 +70,23 @@
background: #fff;
position: absolute;
margin: 5px 0;
z-index: 1001;
z-index: calc(var(--index-normal) + 1);
border: var(--select-dropdown-border);
border-radius: var(--border-radius-small);
overflow: hidden;
box-shadow: var(--select-dropdown-shadow);
}
@b cascader-menu {
display: inline-block;
vertical-align: top;
height: 180px;
height: 204px;
overflow: auto;
border-right: var(--select-dropdown-border);
background-color: var(--select-dropdown-background);
box-sizing: border-box;
margin: 0;
padding: 0;
min-width: 110px;
padding: 6px 0;
min-width: 160px;
&:last-child {
border-right: 0;
......@@ -102,13 +106,13 @@
cursor: pointer;
@e keyword {
color: var(--color-danger);
font-weight: bold;
}
@m extensible {
&:after {
font-family: 'element-icons';
content: "\e602";
content: "\e606";
font-size: 12px;
transform: scale(0.8);
color: rgb(191, 203, 217);
......@@ -132,7 +136,7 @@
color: var(--color-white);
background-color: var(--select-option-selected);
&.hover {
&:hover {
background-color: var(--select-option-selected-hover);
}
}
......
......@@ -12,7 +12,7 @@ export default {
startTime: 'Hora de inicio',
endDate: 'Data de fim',
endTime: 'Hora de fim',
year: 'Ano',
year: '',
month1: 'Janeiro',
month2: 'Fevereiro',
month3: 'Março',
......
......@@ -13,6 +13,7 @@ describe('Cascader', () => {
ref="cascader"
placeholder="请选择"
:options="options"
clearable
v-model="selectedOptions"
></el-cascader>
`,
......@@ -456,6 +457,7 @@ describe('Cascader', () => {
placeholder="请选择"
:options="options"
filterable
:debounce="0"
v-model="selectedOptions"
></el-cascader>
`,
......@@ -507,7 +509,7 @@ describe('Cascader', () => {
const item1 = menuElm.querySelector('.el-cascader-menu__item');
expect(menuElm.children.length).to.be.equal(1);
expect(menuElm.children[0].children.length).to.be.equal(1);
expect(menuElm.children[0].children.length).to.be.equal(3);
done();
item1.click();
......@@ -521,4 +523,106 @@ describe('Cascader', () => {
}, 500);
}, 300);
});
it('props', done => {
vm = createVue({
template: `
<el-cascader
ref="cascader"
:options="options"
:props="props"
v-model="selectedOptions"
></el-cascader>
`,
data() {
return {
options: [{
label: 'Zhejiang',
cities: [{
label: 'Hangzhou'
}, {
label: 'NingBo'
}]
}, {
label: 'Jiangsu',
cities: [{
label: 'Nanjing'
}]
}],
props: {
value: 'label',
children: 'cities'
},
selectedOptions: []
};
}
}, true);
vm.$el.click();
setTimeout(_ => {
expect(document.body.querySelector('.el-cascader-menus')).to.be.exist;
const menu = vm.$refs.cascader.menu;
const menuElm = menu.$el;
let items = menuElm.querySelectorAll('.el-cascader-menu__item');
expect(items.length).to.equal(2);
items[0].click();
setTimeout(_ => {
items = menuElm.querySelectorAll('.el-cascader-menu__item');
expect(items.length).to.equal(4);
expect(items[items.length - 1].innerText).to.equal('NingBo');
done();
}, 100);
}, 100);
});
it('show last level', done => {
vm = createVue({
template: `
<el-cascader
ref="cascader"
:options="options"
:show-all-levels="false"
v-model="selectedOptions"
></el-cascader>
`,
data() {
return {
options: [{
value: 'zhejiang',
label: 'Zhejiang',
children: [{
value: 'hangzhou',
label: 'Hangzhou',
children: [{
value: 'xihu',
label: 'West Lake'
}]
}, {
value: 'ningbo',
label: 'NingBo',
children: [{
value: 'jiangbei',
label: 'Jiang Bei'
}]
}]
}, {
value: 'jiangsu',
label: 'Jiangsu',
children: [{
value: 'nanjing',
label: 'Nanjing',
children: [{
value: 'zhonghuamen',
label: 'Zhong Hua Men'
}]
}]
}],
selectedOptions: ['zhejiang', 'ningbo', 'jiangbei']
};
}
}, true);
setTimeout(_ => {
const span = vm.$el.querySelector('.el-cascader__label');
expect(span.innerText).to.equal('Jiang Bei');
done();
}, 100);
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment