|
@@ -11,7 +11,7 @@
|
|
|
<transition-group @after-leave="resetInputHeight">
|
|
|
<el-tag
|
|
|
v-for="item in selected"
|
|
|
- :key="item.value"
|
|
|
+ :key="getValueKey(item)"
|
|
|
closable
|
|
|
:hit="item.hitState"
|
|
|
type="primary"
|
|
@@ -67,8 +67,8 @@
|
|
|
</el-input>
|
|
|
<transition
|
|
|
name="el-zoom-in-top"
|
|
|
- @after-leave="doDestroy"
|
|
|
- @after-enter="handleMenuEnter">
|
|
|
+ @before-enter="handleMenuEnter"
|
|
|
+ @after-leave="doDestroy">
|
|
|
<el-select-menu
|
|
|
ref="popper"
|
|
|
v-show="visible && emptyText !== false">
|
|
@@ -105,6 +105,9 @@
|
|
|
import { addClass, removeClass, hasClass } from 'element-ui/src/utils/dom';
|
|
|
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event';
|
|
|
import { t } from 'element-ui/src/locale';
|
|
|
+ import scrollIntoView from 'element-ui/src/utils/scroll-into-view';
|
|
|
+ import { getValueByPath } from 'element-ui/src/utils/util';
|
|
|
+
|
|
|
const sizeMap = {
|
|
|
'large': 42,
|
|
|
'small': 30,
|
|
@@ -194,7 +197,11 @@
|
|
|
return t('el.select.placeholder');
|
|
|
}
|
|
|
},
|
|
|
- defaultFirstOption: Boolean
|
|
|
+ defaultFirstOption: Boolean,
|
|
|
+ valueKey: {
|
|
|
+ type: String,
|
|
|
+ default: 'value'
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
data() {
|
|
@@ -210,13 +217,10 @@
|
|
|
cachedPlaceHolder: '',
|
|
|
optionsCount: 0,
|
|
|
filteredOptionsCount: 0,
|
|
|
- dropdownUl: null,
|
|
|
visible: false,
|
|
|
selectedLabel: '',
|
|
|
hoverIndex: -1,
|
|
|
query: '',
|
|
|
- bottomOverflow: 0,
|
|
|
- topOverflow: 0,
|
|
|
optionsAllDisabled: false,
|
|
|
inputHovering: false,
|
|
|
currentPlaceholder: ''
|
|
@@ -292,7 +296,6 @@
|
|
|
}
|
|
|
});
|
|
|
if (!this.multiple) {
|
|
|
- this.getOverflows();
|
|
|
if (this.selected) {
|
|
|
if (this.filterable && this.allowCreate &&
|
|
|
this.createdSelected && this.createdOption) {
|
|
@@ -353,44 +356,31 @@
|
|
|
}
|
|
|
},
|
|
|
|
|
|
- handleMenuEnter() {
|
|
|
- if (!this.dropdownUl) {
|
|
|
- this.dropdownUl = this.$refs.popper.$el.querySelector('.el-select-dropdown__wrap');
|
|
|
- this.getOverflows();
|
|
|
- }
|
|
|
- if (!this.multiple && this.dropdownUl) {
|
|
|
- this.resetMenuScroll();
|
|
|
- }
|
|
|
+ scrollToOption(className = 'selected') {
|
|
|
+ const menu = this.$refs.popper.$el.querySelector('.el-select-dropdown__wrap');
|
|
|
+ scrollIntoView(menu, menu.getElementsByClassName(className)[0]);
|
|
|
},
|
|
|
|
|
|
- getOverflows() {
|
|
|
- if (this.dropdownUl && this.selected && this.selected.$el) {
|
|
|
- let selectedRect = this.selected.$el.getBoundingClientRect();
|
|
|
- let popperRect = this.$refs.popper.$el.getBoundingClientRect();
|
|
|
- this.bottomOverflow = selectedRect.bottom - popperRect.bottom;
|
|
|
- this.topOverflow = selectedRect.top - popperRect.top;
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- resetMenuScroll() {
|
|
|
- if (this.bottomOverflow > 0) {
|
|
|
- this.dropdownUl.scrollTop += this.bottomOverflow;
|
|
|
- } else if (this.topOverflow < 0) {
|
|
|
- this.dropdownUl.scrollTop += this.topOverflow;
|
|
|
- }
|
|
|
+ handleMenuEnter() {
|
|
|
+ this.$nextTick(() => this.scrollToOption());
|
|
|
},
|
|
|
|
|
|
getOption(value) {
|
|
|
let option;
|
|
|
+ const type = typeof value;
|
|
|
+ const isObject = type !== 'string' && type !== 'number' && type !== 'boolean';
|
|
|
for (let i = this.cachedOptions.length - 1; i >= 0; i--) {
|
|
|
const cachedOption = this.cachedOptions[i];
|
|
|
- if (cachedOption.value === value) {
|
|
|
+ const isEqual = isObject
|
|
|
+ ? getValueByPath(cachedOption.value, this.valueKey) === getValueByPath(value, this.valueKey)
|
|
|
+ : cachedOption.value === value;
|
|
|
+ if (isEqual) {
|
|
|
option = cachedOption;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
if (option) return option;
|
|
|
- const label = typeof value === 'string' || typeof value === 'number'
|
|
|
+ const label = !isObject
|
|
|
? value : '';
|
|
|
let newOption = {
|
|
|
value: value,
|
|
@@ -525,7 +515,7 @@
|
|
|
handleOptionSelect(option) {
|
|
|
if (this.multiple) {
|
|
|
const value = this.value.slice();
|
|
|
- const optionIndex = value.indexOf(option.value);
|
|
|
+ const optionIndex = this.getValueIndex(value, option.value);
|
|
|
if (optionIndex > -1) {
|
|
|
value.splice(optionIndex, 1);
|
|
|
} else if (this.multipleLimit <= 0 || value.length < this.multipleLimit) {
|
|
@@ -541,6 +531,26 @@
|
|
|
this.$emit('input', option.value);
|
|
|
this.visible = false;
|
|
|
}
|
|
|
+ this.$nextTick(() => this.scrollToOption());
|
|
|
+ },
|
|
|
+
|
|
|
+ getValueIndex(arr = [], value) {
|
|
|
+ const type = typeof value;
|
|
|
+ const isObject = type !== 'string' && type !== 'number' && type !== 'boolean';
|
|
|
+ if (!isObject) {
|
|
|
+ return arr.indexOf(value);
|
|
|
+ } else {
|
|
|
+ const valueKey = this.valueKey;
|
|
|
+ let index = -1;
|
|
|
+ arr.some((item, i) => {
|
|
|
+ if (getValueByPath(item, valueKey) === getValueByPath(value, valueKey)) {
|
|
|
+ index = i;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ });
|
|
|
+ return index;
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
toggleMenu() {
|
|
@@ -565,7 +575,6 @@
|
|
|
if (this.hoverIndex === this.options.length) {
|
|
|
this.hoverIndex = 0;
|
|
|
}
|
|
|
- this.resetScrollTop();
|
|
|
if (this.options[this.hoverIndex].disabled === true ||
|
|
|
this.options[this.hoverIndex].groupDisabled === true ||
|
|
|
!this.options[this.hoverIndex].visible) {
|
|
@@ -577,7 +586,6 @@
|
|
|
if (this.hoverIndex < 0) {
|
|
|
this.hoverIndex = this.options.length - 1;
|
|
|
}
|
|
|
- this.resetScrollTop();
|
|
|
if (this.options[this.hoverIndex].disabled === true ||
|
|
|
this.options[this.hoverIndex].groupDisabled === true ||
|
|
|
!this.options[this.hoverIndex].visible) {
|
|
@@ -585,19 +593,7 @@
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- },
|
|
|
-
|
|
|
- resetScrollTop() {
|
|
|
- let bottomOverflowDistance = this.options[this.hoverIndex].$el.getBoundingClientRect().bottom -
|
|
|
- this.$refs.popper.$el.getBoundingClientRect().bottom;
|
|
|
- let topOverflowDistance = this.options[this.hoverIndex].$el.getBoundingClientRect().top -
|
|
|
- this.$refs.popper.$el.getBoundingClientRect().top;
|
|
|
- if (bottomOverflowDistance > 0) {
|
|
|
- this.dropdownUl.scrollTop += bottomOverflowDistance;
|
|
|
- }
|
|
|
- if (topOverflowDistance < 0) {
|
|
|
- this.dropdownUl.scrollTop += topOverflowDistance;
|
|
|
- }
|
|
|
+ this.$nextTick(() => this.scrollToOption('hover'));
|
|
|
},
|
|
|
|
|
|
selectOption() {
|
|
@@ -667,6 +663,15 @@
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ },
|
|
|
+
|
|
|
+ getValueKey(item) {
|
|
|
+ const type = typeof item.value;
|
|
|
+ if (type === 'number' || type === 'string') {
|
|
|
+ return item.value;
|
|
|
+ } else {
|
|
|
+ return getValueByPath(item.value, this.valueKey);
|
|
|
+ }
|
|
|
}
|
|
|
},
|
|
|
|