diff --git a/examples/components/demo-block.vue b/examples/components/demo-block.vue
index 8d03fc501..1f4564b8d 100644
--- a/examples/components/demo-block.vue
+++ b/examples/components/demo-block.vue
@@ -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();
}
diff --git a/examples/docs/en-US/cascader.md b/examples/docs/en-US/cascader.md
index 3eb74a6f2..101bd80d5 100644
--- a/examples/docs/en-US/cascader.md
+++ b/examples/docs/en-US/cascader.md
@@ -1,73 +1,245 @@
-
-
## 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
-
+
+ Child options expand when clicked (default)
+
+
+
+
+ Child options expand when hovered
+
+
+
+
+```
+:::
+
+### With default value
+
+:::demo The default value can be defined with an array.
+```html
+
+
-```
-:::
-
-### Size
-
-:::demo
-```html
-
-
-
-
-
-
-```
-:::
-
-### Hover to expand
-
-Hover to expand the next level options, click to select option.
-
-:::demo
-```html
-
-
+```
+:::
+
+### Filterable
+
+Search and select options with a keyword.
+
+:::demo Adding `filterable` to `el-cascader` enables filtering
+```html
+
+ Only options of the last level can be selected
+
+
+
+ Options of all levels can be selected
+
+
+
+
+```
+:::
+
+### 仅显示最后一级
+
+可以仅在输入框中显示选中项最后一级的标签,而不是选中项所在的完整路径。
+
+:::demo 属性`show-all-levels`定义了是否显示完整的路径,将其赋值为`false`则仅显示最后一级
+```html
+
+
-```
-:::
-
-### 尺寸
-
-:::demo 提供三种尺寸的级联选择器
-```html
-
-
-
-
-
-
-```
-:::
-
-### 移入展开
-
-在鼠标移入时就展开下级菜单,完成选择仍需要进行点击。
-
-:::demo
-```html
-
-
+```
+:::
+
+### 可搜索
+
+可以快捷地搜索选项并选择。
+
+:::demo 将`filterable`赋值为`true`即可打开搜索功能。
+```html
+
+ 只可选择最后一级菜单的选项
+
+
+
+ 可选择任意一级菜单的选项
+
+
+
+
diff --git a/packages/cascader/src/menu.vue b/packages/cascader/src/menu.vue
index ab864df5f..b149bd8a9 100644
--- a/packages/cascader/src/menu.vue
+++ b/packages/cascader/src/menu.vue
@@ -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 (
diff --git a/packages/theme-default/src/cascader.css b/packages/theme-default/src/cascader.css
index 35dc81e7d..5f388ba54 100644
--- a/packages/theme-default/src/cascader.css
+++ b/packages/theme-default/src/cascader.css
@@ -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);
}
}
diff --git a/src/locale/lang/pt.js b/src/locale/lang/pt.js
index 327234ee5..8efcdcb4e 100644
--- a/src/locale/lang/pt.js
+++ b/src/locale/lang/pt.js
@@ -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',
diff --git a/test/unit/specs/cascader.spec.js b/test/unit/specs/cascader.spec.js
index 007cbb907..54973e7ac 100644
--- a/test/unit/specs/cascader.spec.js
+++ b/test/unit/specs/cascader.spec.js
@@ -13,6 +13,7 @@ describe('Cascader', () => {
ref="cascader"
placeholder="请选择"
:options="options"
+ clearable
v-model="selectedOptions"
>
`,
@@ -456,6 +457,7 @@ describe('Cascader', () => {
placeholder="请选择"
:options="options"
filterable
+ :debounce="0"
v-model="selectedOptions"
>
`,
@@ -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: `
+
+ `,
+ 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: `
+
+ `,
+ 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);
+ });
});