2016-10-17 12:34:20 +08:00
|
|
|
<template>
|
|
|
|
<div :class="classes" v-clickoutside="handleClose">
|
|
|
|
<div
|
2016-10-28 17:24:52 +08:00
|
|
|
:class="[prefixCls + '-selection']"
|
2017-03-06 18:24:57 +08:00
|
|
|
ref="reference"
|
2016-10-17 12:34:20 +08:00
|
|
|
@click="toggleMenu">
|
2017-03-06 18:24:57 +08:00
|
|
|
<div class="ivu-tag" v-for="(item, index) in selectedMultiple">
|
2016-10-17 12:34:20 +08:00
|
|
|
<span class="ivu-tag-text">{{ item.label }}</span>
|
2017-03-06 18:24:57 +08:00
|
|
|
<Icon type="ios-close-empty" @click.native.stop="removeTag(index)"></Icon>
|
2016-10-17 12:34:20 +08:00
|
|
|
</div>
|
2016-10-28 17:24:52 +08:00
|
|
|
<span :class="[prefixCls + '-placeholder']" v-show="showPlaceholder && !filterable">{{ placeholder }}</span>
|
|
|
|
<span :class="[prefixCls + '-selected-value']" v-show="!showPlaceholder && !multiple && !filterable">{{ selectedSingle }}</span>
|
2016-10-17 12:34:20 +08:00
|
|
|
<input
|
|
|
|
type="text"
|
|
|
|
v-if="filterable"
|
|
|
|
v-model="query"
|
2016-10-28 17:24:52 +08:00
|
|
|
:class="[prefixCls + '-input']"
|
2016-10-24 14:22:33 +08:00
|
|
|
:placeholder="showPlaceholder ? placeholder : ''"
|
2016-10-24 11:44:11 +08:00
|
|
|
:style="inputStyle"
|
2016-10-24 14:22:33 +08:00
|
|
|
@blur="handleBlur"
|
|
|
|
@keydown="resetInputState"
|
|
|
|
@keydown.delete="handleInputDelete"
|
2017-03-06 18:24:57 +08:00
|
|
|
ref="input">
|
|
|
|
<Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSingleSelect"></Icon>
|
2016-10-28 17:24:52 +08:00
|
|
|
<Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon>
|
2016-10-17 12:34:20 +08:00
|
|
|
</div>
|
2017-03-06 18:24:57 +08:00
|
|
|
<transition name="slide-up">
|
|
|
|
<Drop v-show="visible" ref="dropdown">
|
|
|
|
<ul v-show="notFound" :class="[prefixCls + '-not-found']"><li>{{ notFoundText }}</li></ul>
|
|
|
|
<ul v-show="!notFound" :class="[prefixCls + '-dropdown-list']" ref="options"><slot></slot></ul>
|
|
|
|
</Drop>
|
|
|
|
</transition>
|
2016-10-17 12:34:20 +08:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script>
|
|
|
|
import Icon from '../icon';
|
2017-03-06 18:24:57 +08:00
|
|
|
import Drop from './dropdown.vue';
|
2016-10-17 12:34:20 +08:00
|
|
|
import clickoutside from '../../directives/clickoutside';
|
2016-11-03 13:54:21 +08:00
|
|
|
import { oneOf, MutationObserver } from '../../utils/assist';
|
2017-01-11 18:04:29 +08:00
|
|
|
import { t } from '../../locale';
|
2017-03-06 18:24:57 +08:00
|
|
|
import Emitter from '../../mixins/emitter';
|
2016-10-17 12:34:20 +08:00
|
|
|
|
|
|
|
const prefixCls = 'ivu-select';
|
|
|
|
|
|
|
|
export default {
|
2017-01-13 17:10:57 +08:00
|
|
|
name: 'iSelect',
|
2017-03-06 18:24:57 +08:00
|
|
|
mixins: [ Emitter ],
|
|
|
|
components: { Icon, Drop },
|
2016-10-17 12:34:20 +08:00
|
|
|
directives: { clickoutside },
|
|
|
|
props: {
|
2017-03-06 18:24:57 +08:00
|
|
|
value: {
|
2016-10-17 12:34:20 +08:00
|
|
|
type: [String, Number, Array],
|
|
|
|
default: ''
|
|
|
|
},
|
|
|
|
multiple: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
disabled: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
clearable: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
placeholder: {
|
|
|
|
type: String,
|
2017-01-11 18:04:29 +08:00
|
|
|
default () {
|
|
|
|
return t('i.select.placeholder');
|
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
},
|
|
|
|
filterable: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
},
|
|
|
|
filterMethod: {
|
|
|
|
type: Function
|
|
|
|
},
|
|
|
|
size: {
|
|
|
|
validator (value) {
|
2016-10-25 09:10:02 +08:00
|
|
|
return oneOf(value, ['small', 'large', 'default']);
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
labelInValue: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
2016-10-24 16:42:03 +08:00
|
|
|
},
|
|
|
|
notFoundText: {
|
|
|
|
type: String,
|
2017-01-11 18:04:29 +08:00
|
|
|
default () {
|
|
|
|
return t('i.select.noMatch');
|
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
data () {
|
|
|
|
return {
|
|
|
|
prefixCls: prefixCls,
|
|
|
|
visible: false,
|
|
|
|
options: [],
|
|
|
|
optionInstances: [],
|
|
|
|
selectedSingle: '', // label
|
|
|
|
selectedMultiple: [],
|
|
|
|
focusIndex: 0,
|
|
|
|
query: '',
|
2016-10-24 14:22:33 +08:00
|
|
|
inputLength: 20,
|
2016-11-03 13:54:21 +08:00
|
|
|
notFound: false,
|
2017-03-06 18:24:57 +08:00
|
|
|
slotChangeDuration: false, // if slot change duration and in multiple, set true and after slot change, set false
|
|
|
|
model: this.value
|
2016-12-25 22:49:42 +08:00
|
|
|
};
|
2016-10-17 12:34:20 +08:00
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
classes () {
|
|
|
|
return [
|
2016-10-28 18:27:04 +08:00
|
|
|
`${prefixCls}`,
|
2016-10-17 12:34:20 +08:00
|
|
|
{
|
2016-10-28 18:27:04 +08:00
|
|
|
[`${prefixCls}-visible`]: this.visible,
|
|
|
|
[`${prefixCls}-disabled`]: this.disabled,
|
|
|
|
[`${prefixCls}-multiple`]: this.multiple,
|
|
|
|
[`${prefixCls}-single`]: !this.multiple,
|
|
|
|
[`${prefixCls}-show-clear`]: this.showCloseIcon,
|
|
|
|
[`${prefixCls}-${this.size}`]: !!this.size
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
2016-12-25 22:49:42 +08:00
|
|
|
];
|
2016-10-17 12:34:20 +08:00
|
|
|
},
|
|
|
|
showPlaceholder () {
|
|
|
|
let status = false;
|
|
|
|
|
|
|
|
if ((typeof this.model) === 'string') {
|
|
|
|
if (this.model === '') {
|
|
|
|
status = true;
|
|
|
|
}
|
|
|
|
} else if (Array.isArray(this.model)) {
|
|
|
|
if (!this.model.length) {
|
|
|
|
status = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
},
|
|
|
|
showCloseIcon () {
|
|
|
|
return !this.multiple && this.clearable && !this.showPlaceholder;
|
|
|
|
},
|
|
|
|
inputStyle () {
|
|
|
|
let style = {};
|
|
|
|
|
|
|
|
if (this.multiple) {
|
2016-10-24 14:22:33 +08:00
|
|
|
if (this.showPlaceholder) {
|
|
|
|
style.width = '100%';
|
|
|
|
} else {
|
2016-10-28 18:27:04 +08:00
|
|
|
style.width = `${this.inputLength}px`;
|
2016-10-24 14:22:33 +08:00
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return style;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
toggleMenu () {
|
|
|
|
if (this.disabled) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.visible = !this.visible;
|
|
|
|
},
|
|
|
|
hideMenu () {
|
|
|
|
this.visible = false;
|
|
|
|
this.focusIndex = 0;
|
2017-03-06 18:24:57 +08:00
|
|
|
this.broadcast('iOption', 'on-select-close');
|
2016-10-17 12:34:20 +08:00
|
|
|
},
|
|
|
|
// find option component
|
|
|
|
findChild (cb) {
|
|
|
|
const find = function (child) {
|
|
|
|
const name = child.$options.componentName;
|
|
|
|
|
|
|
|
if (name) {
|
|
|
|
cb(child);
|
|
|
|
} else if (child.$children.length) {
|
|
|
|
child.$children.forEach((innerChild) => {
|
|
|
|
find(innerChild, cb);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (this.optionInstances.length) {
|
|
|
|
this.optionInstances.forEach((child) => {
|
|
|
|
find(child);
|
2016-12-25 22:49:42 +08:00
|
|
|
});
|
2016-10-17 12:34:20 +08:00
|
|
|
} else {
|
|
|
|
this.$children.forEach((child) => {
|
|
|
|
find(child);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2016-11-03 13:54:21 +08:00
|
|
|
updateOptions (init, slot = false) {
|
2016-10-17 12:34:20 +08:00
|
|
|
let options = [];
|
|
|
|
let index = 1;
|
|
|
|
|
|
|
|
this.findChild((child) => {
|
|
|
|
options.push({
|
|
|
|
value: child.value,
|
|
|
|
label: (child.label === undefined) ? child.$el.innerHTML : child.label
|
|
|
|
});
|
|
|
|
child.index = index++;
|
|
|
|
|
|
|
|
if (init) {
|
|
|
|
this.optionInstances.push(child);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.options = options;
|
|
|
|
|
|
|
|
if (init) {
|
2016-11-03 13:54:21 +08:00
|
|
|
this.updateSingleSelected(true, slot);
|
|
|
|
this.updateMultipleSelected(true, slot);
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
},
|
2016-11-03 13:54:21 +08:00
|
|
|
updateSingleSelected (init = false, slot = false) {
|
2016-10-17 12:34:20 +08:00
|
|
|
const type = typeof this.model;
|
|
|
|
|
|
|
|
if (type === 'string' || type === 'number') {
|
2016-11-03 13:54:21 +08:00
|
|
|
let findModel = false;
|
|
|
|
|
2016-10-17 12:34:20 +08:00
|
|
|
for (let i = 0; i < this.options.length; i++) {
|
|
|
|
if (this.model === this.options[i].value) {
|
|
|
|
this.selectedSingle = this.options[i].label;
|
2016-11-03 13:54:21 +08:00
|
|
|
findModel = true;
|
2016-10-17 12:34:20 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2016-11-03 13:54:21 +08:00
|
|
|
|
|
|
|
if (slot && !findModel) {
|
|
|
|
this.model = '';
|
|
|
|
this.query = '';
|
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
this.toggleSingleSelected(this.model, init);
|
|
|
|
},
|
|
|
|
clearSingleSelect () {
|
|
|
|
if (this.showCloseIcon) {
|
|
|
|
this.findChild((child) => {
|
|
|
|
child.selected = false;
|
|
|
|
});
|
|
|
|
this.model = '';
|
2016-10-24 11:44:11 +08:00
|
|
|
|
|
|
|
if (this.filterable) {
|
|
|
|
this.query = '';
|
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
},
|
2016-11-03 13:54:21 +08:00
|
|
|
updateMultipleSelected (init = false, slot = false) {
|
2016-10-17 12:34:20 +08:00
|
|
|
if (this.multiple && Array.isArray(this.model)) {
|
|
|
|
let selected = [];
|
|
|
|
|
|
|
|
for (let i = 0; i < this.model.length; i++) {
|
|
|
|
const model = this.model[i];
|
|
|
|
|
|
|
|
for (let j = 0; j < this.options.length; j++) {
|
|
|
|
const option = this.options[j];
|
|
|
|
|
|
|
|
if (model === option.value) {
|
|
|
|
selected.push({
|
|
|
|
value: option.value,
|
|
|
|
label: option.label
|
2016-12-25 22:49:42 +08:00
|
|
|
});
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.selectedMultiple = selected;
|
|
|
|
|
2016-11-03 13:54:21 +08:00
|
|
|
if (slot) {
|
|
|
|
let selectedModel = [];
|
|
|
|
|
|
|
|
for (let i = 0; i < selected.length; i++) {
|
|
|
|
selectedModel.push(selected[i].value);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if slot change and remove a selected option, emit user
|
|
|
|
if (this.model.length === selectedModel.length) {
|
|
|
|
this.slotChangeDuration = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.model = selectedModel;
|
|
|
|
}
|
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
this.toggleMultipleSelected(this.model, init);
|
|
|
|
},
|
|
|
|
removeTag (index) {
|
|
|
|
if (this.disabled) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
this.model.splice(index, 1);
|
2016-10-24 14:22:33 +08:00
|
|
|
|
|
|
|
if (this.filterable && this.visible) {
|
2017-03-06 18:24:57 +08:00
|
|
|
this.$refs.input.focus();
|
2016-10-24 14:22:33 +08:00
|
|
|
}
|
|
|
|
|
2017-03-06 18:24:57 +08:00
|
|
|
this.broadcast('Drop', 'on-update-popper');
|
2016-10-17 12:34:20 +08:00
|
|
|
},
|
|
|
|
// to select option for single
|
|
|
|
toggleSingleSelected (value, init = false) {
|
|
|
|
if (!this.multiple) {
|
|
|
|
let label = '';
|
|
|
|
|
|
|
|
this.findChild((child) => {
|
|
|
|
if (child.value === value) {
|
|
|
|
child.selected = true;
|
|
|
|
label = (child.label === undefined) ? child.$el.innerHTML : child.label;
|
|
|
|
} else {
|
|
|
|
child.selected = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
this.hideMenu();
|
|
|
|
|
|
|
|
if (!init) {
|
|
|
|
if (this.labelInValue) {
|
|
|
|
this.$emit('on-change', {
|
|
|
|
value: value,
|
|
|
|
label: label
|
|
|
|
});
|
2017-03-09 11:14:40 +08:00
|
|
|
this.dispatch('FormItem', 'on-form-change', {
|
|
|
|
value: value,
|
|
|
|
label: label
|
|
|
|
});
|
2016-10-17 12:34:20 +08:00
|
|
|
} else {
|
|
|
|
this.$emit('on-change', value);
|
2017-03-09 11:14:40 +08:00
|
|
|
this.dispatch('FormItem', 'on-form-change', value);
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
// to select option for multiple
|
|
|
|
toggleMultipleSelected (value, init = false) {
|
|
|
|
if (this.multiple) {
|
|
|
|
let hybridValue = [];
|
|
|
|
for (let i = 0; i < value.length; i++) {
|
|
|
|
hybridValue.push({
|
|
|
|
value: value[i]
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
this.findChild((child) => {
|
|
|
|
const index = value.indexOf(child.value);
|
|
|
|
|
|
|
|
if (index >= 0) {
|
|
|
|
child.selected = true;
|
|
|
|
hybridValue[index].label = (child.label === undefined) ? child.$el.innerHTML : child.label;
|
|
|
|
} else {
|
|
|
|
child.selected = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!init) {
|
|
|
|
if (this.labelInValue) {
|
|
|
|
this.$emit('on-change', hybridValue);
|
2017-03-09 11:14:40 +08:00
|
|
|
this.dispatch('FormItem', 'on-form-change', hybridValue);
|
|
|
|
} else {
|
2016-10-17 12:34:20 +08:00
|
|
|
this.$emit('on-change', value);
|
2017-03-09 11:14:40 +08:00
|
|
|
this.dispatch('FormItem', 'on-form-change', value);
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
handleClose () {
|
|
|
|
this.hideMenu();
|
|
|
|
},
|
|
|
|
handleKeydown (e) {
|
|
|
|
if (this.visible) {
|
|
|
|
const keyCode = e.keyCode;
|
|
|
|
// Esc slide-up
|
|
|
|
if (keyCode === 27) {
|
|
|
|
e.preventDefault();
|
|
|
|
this.hideMenu();
|
|
|
|
}
|
|
|
|
// next
|
|
|
|
if (keyCode === 40) {
|
|
|
|
e.preventDefault();
|
|
|
|
this.navigateOptions('next');
|
|
|
|
}
|
|
|
|
// prev
|
|
|
|
if (keyCode === 38) {
|
|
|
|
e.preventDefault();
|
|
|
|
this.navigateOptions('prev');
|
|
|
|
}
|
|
|
|
// enter
|
|
|
|
if (keyCode === 13) {
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
this.findChild((child) => {
|
|
|
|
if (child.isFocus) {
|
|
|
|
child.select();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
navigateOptions (direction) {
|
|
|
|
if (direction === 'next') {
|
|
|
|
const next = this.focusIndex + 1;
|
|
|
|
this.focusIndex = (this.focusIndex === this.options.length) ? 1 : next;
|
|
|
|
} else if (direction === 'prev') {
|
|
|
|
const prev = this.focusIndex - 1;
|
|
|
|
this.focusIndex = (this.focusIndex <= 1) ? this.options.length : prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
let child_status = {
|
2016-10-24 11:44:11 +08:00
|
|
|
disabled: false,
|
|
|
|
hidden: false
|
2016-10-17 12:34:20 +08:00
|
|
|
};
|
|
|
|
|
2016-10-24 11:44:11 +08:00
|
|
|
let find_deep = false; // can next find allowed
|
|
|
|
|
2016-10-17 12:34:20 +08:00
|
|
|
this.findChild((child) => {
|
|
|
|
if (child.index === this.focusIndex) {
|
|
|
|
child_status.disabled = child.disabled;
|
2016-10-24 11:44:11 +08:00
|
|
|
child_status.hidden = child.hidden;
|
2016-10-17 12:34:20 +08:00
|
|
|
|
2016-10-24 11:44:11 +08:00
|
|
|
if (!child.disabled && !child.hidden) {
|
2016-10-17 12:34:20 +08:00
|
|
|
child.isFocus = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
child.isFocus = false;
|
|
|
|
}
|
2016-10-24 11:44:11 +08:00
|
|
|
|
|
|
|
if (!child.hidden && !child.disabled) {
|
|
|
|
find_deep = true;
|
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
this.resetScrollTop();
|
|
|
|
|
2016-10-24 11:44:11 +08:00
|
|
|
if ((child_status.disabled || child_status.hidden) && find_deep) {
|
2016-10-17 12:34:20 +08:00
|
|
|
this.navigateOptions(direction);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
resetScrollTop () {
|
|
|
|
const index = this.focusIndex - 1;
|
|
|
|
let bottomOverflowDistance = this.optionInstances[index].$el.getBoundingClientRect().bottom - this.$refs.dropdown.$el.getBoundingClientRect().bottom;
|
|
|
|
let topOverflowDistance = this.optionInstances[index].$el.getBoundingClientRect().top - this.$refs.dropdown.$el.getBoundingClientRect().top;
|
|
|
|
|
|
|
|
if (bottomOverflowDistance > 0) {
|
|
|
|
this.$refs.dropdown.$el.scrollTop += bottomOverflowDistance;
|
|
|
|
}
|
|
|
|
if (topOverflowDistance < 0) {
|
|
|
|
this.$refs.dropdown.$el.scrollTop += topOverflowDistance;
|
|
|
|
}
|
2016-10-24 11:44:11 +08:00
|
|
|
},
|
|
|
|
handleBlur () {
|
|
|
|
setTimeout(() => {
|
|
|
|
const model = this.model;
|
|
|
|
|
|
|
|
if (this.multiple) {
|
2017-01-10 20:44:35 +08:00
|
|
|
this.query = '';
|
2016-10-24 11:44:11 +08:00
|
|
|
} else {
|
|
|
|
if (model !== '') {
|
|
|
|
this.findChild((child) => {
|
|
|
|
if (child.value === model) {
|
2017-01-09 02:03:28 -06:00
|
|
|
this.query = child.label === undefined ? child.searchLabel : child.label;
|
2016-10-24 11:44:11 +08:00
|
|
|
}
|
|
|
|
});
|
2017-01-10 20:44:35 +08:00
|
|
|
} else {
|
|
|
|
this.query = '';
|
2016-10-24 11:44:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}, 300);
|
2016-10-24 14:22:33 +08:00
|
|
|
},
|
|
|
|
resetInputState () {
|
2017-03-06 18:24:57 +08:00
|
|
|
this.inputLength = this.$refs.input.value.length * 12 + 20;
|
2016-10-24 14:22:33 +08:00
|
|
|
},
|
|
|
|
handleInputDelete () {
|
|
|
|
if (this.multiple && this.model.length && this.query === '') {
|
|
|
|
this.removeTag(this.model.length - 1);
|
|
|
|
}
|
2016-11-03 13:54:21 +08:00
|
|
|
},
|
|
|
|
// use when slot changed
|
|
|
|
slotChange () {
|
|
|
|
this.options = [];
|
|
|
|
this.optionInstances = [];
|
2016-12-08 22:34:52 +08:00
|
|
|
},
|
|
|
|
setQuery (query) {
|
|
|
|
if (!this.filterable) return;
|
|
|
|
this.query = query;
|
2017-02-09 11:48:44 +08:00
|
|
|
},
|
|
|
|
modelToQuery() {
|
2017-02-09 20:01:50 +08:00
|
|
|
if (!this.multiple && this.filterable && this.model) {
|
|
|
|
this.findChild((child) => {
|
|
|
|
if (this.model === child.value) {
|
|
|
|
if (child.label) {
|
|
|
|
this.query = child.label;
|
|
|
|
} else if (child.searchLabel) {
|
|
|
|
this.query = child.searchLabel;
|
|
|
|
} else {
|
|
|
|
this.query = child.value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
},
|
2017-03-06 18:24:57 +08:00
|
|
|
mounted () {
|
2017-02-09 20:01:50 +08:00
|
|
|
this.modelToQuery();
|
2017-01-03 12:05:25 +08:00
|
|
|
|
2016-10-17 12:34:20 +08:00
|
|
|
this.updateOptions(true);
|
|
|
|
document.addEventListener('keydown', this.handleKeydown);
|
2016-11-03 13:54:21 +08:00
|
|
|
|
|
|
|
// watch slot changed
|
|
|
|
if (MutationObserver) {
|
|
|
|
this.observer = new MutationObserver(() => {
|
2017-02-09 20:01:50 +08:00
|
|
|
this.modelToQuery();
|
2016-11-03 13:54:21 +08:00
|
|
|
this.slotChange();
|
|
|
|
this.updateOptions(true, true);
|
|
|
|
});
|
|
|
|
|
2017-03-06 18:24:57 +08:00
|
|
|
this.observer.observe(this.$refs.options, {
|
2016-11-03 13:54:21 +08:00
|
|
|
// attributes: true,
|
|
|
|
childList: true,
|
|
|
|
characterData: true,
|
|
|
|
subtree: true
|
|
|
|
});
|
|
|
|
}
|
2017-03-06 18:24:57 +08:00
|
|
|
|
|
|
|
this.$on('on-select-selected', (value) => {
|
|
|
|
if (this.model === value) {
|
|
|
|
this.hideMenu();
|
|
|
|
} else {
|
|
|
|
if (this.multiple) {
|
|
|
|
const index = this.model.indexOf(value);
|
|
|
|
if (index >= 0) {
|
|
|
|
this.removeTag(index);
|
|
|
|
} else {
|
|
|
|
this.model.push(value);
|
|
|
|
this.broadcast('Drop', 'on-update-popper');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.filterable) {
|
|
|
|
this.query = '';
|
|
|
|
this.$refs.input.focus();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
this.model = value;
|
|
|
|
|
|
|
|
if (this.filterable) {
|
|
|
|
this.findChild((child) => {
|
|
|
|
if (child.value === value) {
|
|
|
|
this.query = child.label === undefined ? child.searchLabel : child.label;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2016-10-17 12:34:20 +08:00
|
|
|
},
|
|
|
|
beforeDestroy () {
|
|
|
|
document.removeEventListener('keydown', this.handleKeydown);
|
2016-11-03 13:54:21 +08:00
|
|
|
if (this.observer) {
|
|
|
|
this.observer.disconnect();
|
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
},
|
|
|
|
watch: {
|
2017-03-06 18:24:57 +08:00
|
|
|
value (val) {
|
|
|
|
this.model = val;
|
|
|
|
},
|
2016-10-17 12:34:20 +08:00
|
|
|
model () {
|
2017-03-06 18:24:57 +08:00
|
|
|
this.$emit('input', this.model);
|
2017-02-09 20:01:50 +08:00
|
|
|
this.modelToQuery();
|
2016-10-17 12:34:20 +08:00
|
|
|
if (this.multiple) {
|
2016-11-03 13:54:21 +08:00
|
|
|
if (this.slotChangeDuration) {
|
|
|
|
this.slotChangeDuration = false;
|
|
|
|
} else {
|
|
|
|
this.updateMultipleSelected();
|
|
|
|
}
|
2016-10-17 12:34:20 +08:00
|
|
|
} else {
|
|
|
|
this.updateSingleSelected();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
visible (val) {
|
|
|
|
if (val) {
|
2016-10-24 14:22:33 +08:00
|
|
|
if (this.multiple && this.filterable) {
|
2017-03-06 18:24:57 +08:00
|
|
|
this.$refs.input.focus();
|
2016-10-24 14:22:33 +08:00
|
|
|
}
|
2017-03-06 18:24:57 +08:00
|
|
|
this.broadcast('Drop', 'on-update-popper');
|
2016-10-17 12:34:20 +08:00
|
|
|
} else {
|
2016-10-24 18:07:24 +08:00
|
|
|
if (this.filterable) {
|
2017-03-06 18:24:57 +08:00
|
|
|
this.$refs.input.blur();
|
2016-10-24 18:07:24 +08:00
|
|
|
}
|
2017-03-06 18:24:57 +08:00
|
|
|
this.broadcast('Drop', 'on-destroy-popper');
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
2016-10-24 11:44:11 +08:00
|
|
|
},
|
|
|
|
query (val) {
|
2017-03-06 18:24:57 +08:00
|
|
|
// todo 这里会重复
|
|
|
|
this.broadcast('OptionGroup', 'on-query-change', val);
|
|
|
|
this.broadcast('iOption', 'on-query-change', val);
|
2016-10-24 14:22:33 +08:00
|
|
|
let is_hidden = true;
|
|
|
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
this.findChild((child) => {
|
|
|
|
if (!child.hidden) {
|
|
|
|
is_hidden = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.notFound = is_hidden;
|
|
|
|
});
|
2017-03-06 18:24:57 +08:00
|
|
|
this.broadcast('Drop', 'on-update-popper');
|
2016-10-17 12:34:20 +08:00
|
|
|
}
|
|
|
|
}
|
2016-12-25 22:49:42 +08:00
|
|
|
};
|
2016-10-28 17:24:52 +08:00
|
|
|
</script>
|