Select support remote search
This commit is contained in:
parent
28587238de
commit
01b54e3021
9 changed files with 167 additions and 51 deletions
|
@ -1,8 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div style="width: 200px;margin: 100px;">
|
<div style="width: 200px;margin: 100px;">
|
||||||
<i-select v-model="model" filterable clearable style="width:200px">
|
<i-select v-model="model" filterable remote :remote-method="remoteMethod" :loading="loading" clearable style="width:200px">
|
||||||
<i-option :value="option.value" v-for="option in options" :key="option">{{option.label}}</i-option>
|
<i-option v-for="option in options" :value="option.value" :key="option">{{option.label}}</i-option>
|
||||||
</i-select>
|
</i-select>
|
||||||
|
<!--<Button @click="handleAdd">+</Button>-->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -10,26 +11,85 @@
|
||||||
export default {
|
export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
model: 1,
|
model: '',
|
||||||
options: [
|
options: [
|
||||||
|
|
||||||
]
|
],
|
||||||
|
list: [],
|
||||||
|
loading: false,
|
||||||
|
states: ["Alabama", "Alaska", "Arizona",
|
||||||
|
"Arkansas", "California", "Colorado",
|
||||||
|
"Connecticut", "Delaware", "Florida",
|
||||||
|
"Georgia", "Hawaii", "Idaho", "Illinois",
|
||||||
|
"Indiana", "Iowa", "Kansas", "Kentucky",
|
||||||
|
"Louisiana", "Maine", "Maryland",
|
||||||
|
"Massachusetts", "Michigan", "Minnesota",
|
||||||
|
"Mississippi", "Missouri", "Montana",
|
||||||
|
"Nebraska", "Nevada", "New Hampshire",
|
||||||
|
"New Jersey", "New Mexico", "New York",
|
||||||
|
"North Carolina", "North Dakota", "Ohio",
|
||||||
|
"Oklahoma", "Oregon", "Pennsylvania",
|
||||||
|
"Rhode Island", "South Carolina",
|
||||||
|
"South Dakota", "Tennessee", "Texas",
|
||||||
|
"Utah", "Vermont", "Virginia",
|
||||||
|
"Washington", "West Virginia", "Wisconsin",
|
||||||
|
"Wyoming"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.options = [{
|
this.options = [
|
||||||
label: '全部',
|
// {
|
||||||
value: 0
|
// label: '全部',
|
||||||
},{
|
// value: 0
|
||||||
label: '苹果',
|
// },{
|
||||||
value: 1
|
// label: '苹果',
|
||||||
},{
|
// value: 1
|
||||||
label: '香蕉',
|
// },{
|
||||||
value: 2
|
// label: '香蕉',
|
||||||
},{
|
// value: 2
|
||||||
label: '西瓜',
|
// },{
|
||||||
value: 3
|
// label: '西瓜',
|
||||||
}];
|
// value: 3
|
||||||
|
// }
|
||||||
|
];
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleAdd () {
|
||||||
|
this.options = [
|
||||||
|
{
|
||||||
|
label: '全部',
|
||||||
|
value: 0
|
||||||
|
},{
|
||||||
|
label: '苹果',
|
||||||
|
value: 1
|
||||||
|
},{
|
||||||
|
label: '香蕉',
|
||||||
|
value: 2
|
||||||
|
},{
|
||||||
|
label: '西瓜',
|
||||||
|
value: 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
remoteMethod (query) {
|
||||||
|
if (query !== '') {
|
||||||
|
this.loading = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loading = false;
|
||||||
|
this.options = this.list.filter(item => {
|
||||||
|
return item.label.toLowerCase()
|
||||||
|
.indexOf(query.toLowerCase()) > -1;
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
} else {
|
||||||
|
this.options = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.list = this.states.map(item => {
|
||||||
|
return { value: item, label: item };
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -22,12 +22,16 @@
|
||||||
@keydown.delete="handleInputDelete"
|
@keydown.delete="handleInputDelete"
|
||||||
ref="input">
|
ref="input">
|
||||||
<Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSingleSelect"></Icon>
|
<Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSingleSelect"></Icon>
|
||||||
<Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon>
|
<Icon type="arrow-down-b" :class="[prefixCls + '-arrow']" v-if="!remote"></Icon>
|
||||||
</div>
|
</div>
|
||||||
<transition :name="transitionName">
|
<transition :name="transitionName">
|
||||||
<Drop v-show="visible" :placement="placement" ref="dropdown">
|
<Drop v-show="(visible && options.length) ||
|
||||||
<ul v-show="notFound" :class="[prefixCls + '-not-found']"><li>{{ localeNotFoundText }}</li></ul>
|
(visible && !options.length && loading) ||
|
||||||
<ul v-show="!notFound" :class="[prefixCls + '-dropdown-list']" ref="options"><slot></slot></ul>
|
(visible && remote && !loading && !options.length && query !== '')" :placement="placement" ref="dropdown">
|
||||||
|
<!--<Drop v-show="visible" :placement="placement" ref="dropdown">-->
|
||||||
|
<ul v-show="(notFound && !remote) || (remote && !loading && !options.length)" :class="[prefixCls + '-not-found']"><li>{{ localeNotFoundText }}</li></ul>
|
||||||
|
<ul v-show="(!notFound && !remote) || (remote && !loading && !notFound)" :class="[prefixCls + '-dropdown-list']" ref="options"><slot></slot></ul>
|
||||||
|
<ul v-show="loading" :class="[prefixCls + '-loading']">{{ localeLoadingText }}</ul>
|
||||||
</Drop>
|
</Drop>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,6 +78,20 @@
|
||||||
filterMethod: {
|
filterMethod: {
|
||||||
type: Function
|
type: Function
|
||||||
},
|
},
|
||||||
|
remote: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
remoteMethod: {
|
||||||
|
type: Function
|
||||||
|
},
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
loadingText: {
|
||||||
|
type: String
|
||||||
|
},
|
||||||
size: {
|
size: {
|
||||||
validator (value) {
|
validator (value) {
|
||||||
return oneOf(value, ['small', 'large', 'default']);
|
return oneOf(value, ['small', 'large', 'default']);
|
||||||
|
@ -103,6 +121,7 @@
|
||||||
selectedMultiple: [],
|
selectedMultiple: [],
|
||||||
focusIndex: 0,
|
focusIndex: 0,
|
||||||
query: '',
|
query: '',
|
||||||
|
selectToChangeQuery: false, // when select an option, set this first and set query, because query is watching, it will emit event
|
||||||
inputLength: 20,
|
inputLength: 20,
|
||||||
notFound: false,
|
notFound: false,
|
||||||
slotChangeDuration: false, // if slot change duration and in multiple, set true and after slot change, set false
|
slotChangeDuration: false, // if slot change duration and in multiple, set true and after slot change, set false
|
||||||
|
@ -168,6 +187,13 @@
|
||||||
return this.notFoundText;
|
return this.notFoundText;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
localeLoadingText () {
|
||||||
|
if (this.loadingText === undefined) {
|
||||||
|
return this.t('i.select.loading');
|
||||||
|
} else {
|
||||||
|
return this.loadingText;
|
||||||
|
}
|
||||||
|
},
|
||||||
transitionName () {
|
transitionName () {
|
||||||
return this.placement === 'bottom' ? 'slide-up' : 'slide-down';
|
return this.placement === 'bottom' ? 'slide-up' : 'slide-down';
|
||||||
}
|
}
|
||||||
|
@ -187,15 +213,18 @@
|
||||||
},
|
},
|
||||||
// find option component
|
// find option component
|
||||||
findChild (cb) {
|
findChild (cb) {
|
||||||
|
const _this = this;
|
||||||
const find = function (child) {
|
const find = function (child) {
|
||||||
const name = child.$options.componentName;
|
const name = child.$options.componentName;
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
cb(child);
|
cb(child);
|
||||||
} else if (child.$children.length) {
|
} else if (child.$children.length) {
|
||||||
child.$children.forEach((innerChild) => {
|
_this.$nextTick(() => {
|
||||||
find(innerChild, cb);
|
child.$children.forEach((innerChild) => {
|
||||||
});
|
find(innerChild, cb);
|
||||||
|
});
|
||||||
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -228,8 +257,10 @@
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
||||||
if (init) {
|
if (init) {
|
||||||
this.updateSingleSelected(true, slot);
|
if (!this.remote) {
|
||||||
this.updateMultipleSelected(true, slot);
|
this.updateSingleSelected(true, slot);
|
||||||
|
this.updateMultipleSelected(true, slot);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateSingleSelected (init = false, slot = false) {
|
updateSingleSelected (init = false, slot = false) {
|
||||||
|
@ -535,18 +566,22 @@
|
||||||
document.addEventListener('keydown', this.handleKeydown);
|
document.addEventListener('keydown', this.handleKeydown);
|
||||||
|
|
||||||
this.$on('append', () => {
|
this.$on('append', () => {
|
||||||
this.modelToQuery();
|
if (!this.remote) {
|
||||||
this.$nextTick(() => {
|
this.modelToQuery();
|
||||||
this.broadcastQuery('');
|
this.$nextTick(() => {
|
||||||
});
|
this.broadcastQuery('');
|
||||||
|
});
|
||||||
|
}
|
||||||
this.slotChange();
|
this.slotChange();
|
||||||
this.updateOptions(true, true);
|
this.updateOptions(true, true);
|
||||||
});
|
});
|
||||||
this.$on('remove', () => {
|
this.$on('remove', () => {
|
||||||
this.modelToQuery();
|
if (!this.remote) {
|
||||||
this.$nextTick(() => {
|
this.modelToQuery();
|
||||||
this.broadcastQuery('');
|
this.$nextTick(() => {
|
||||||
});
|
this.broadcastQuery('');
|
||||||
|
});
|
||||||
|
}
|
||||||
this.slotChange();
|
this.slotChange();
|
||||||
this.updateOptions(true, true);
|
this.updateOptions(true, true);
|
||||||
});
|
});
|
||||||
|
@ -565,6 +600,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.filterable) {
|
if (this.filterable) {
|
||||||
|
this.selectToChangeQuery = true;
|
||||||
this.query = '';
|
this.query = '';
|
||||||
this.$refs.input.focus();
|
this.$refs.input.focus();
|
||||||
}
|
}
|
||||||
|
@ -574,6 +610,7 @@
|
||||||
if (this.filterable) {
|
if (this.filterable) {
|
||||||
this.findChild((child) => {
|
this.findChild((child) => {
|
||||||
if (child.value === value) {
|
if (child.value === value) {
|
||||||
|
this.selectToChangeQuery = true;
|
||||||
this.query = child.label === undefined ? child.searchLabel : child.label;
|
this.query = child.label === undefined ? child.searchLabel : child.label;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -625,20 +662,29 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
query (val) {
|
query (val) {
|
||||||
this.$emit('on-query-change', val);
|
if (this.remote && this.remoteMethod) {
|
||||||
|
if (!this.selectToChangeQuery) {
|
||||||
|
this.$emit('on-query-change', val);
|
||||||
|
this.remoteMethod(val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!this.selectToChangeQuery) {
|
||||||
|
this.$emit('on-query-change', val);
|
||||||
|
}
|
||||||
|
this.broadcastQuery(val);
|
||||||
|
|
||||||
this.broadcastQuery(val);
|
let is_hidden = true;
|
||||||
|
|
||||||
let is_hidden = true;
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.findChild((child) => {
|
this.findChild((child) => {
|
||||||
if (!child.hidden) {
|
if (!child.hidden) {
|
||||||
is_hidden = false;
|
is_hidden = false;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
this.notFound = is_hidden;
|
||||||
});
|
});
|
||||||
this.notFound = is_hidden;
|
}
|
||||||
});
|
this.selectToChangeQuery = false;
|
||||||
this.broadcast('Drop', 'on-update-popper');
|
this.broadcast('Drop', 'on-update-popper');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,8 @@ export default {
|
||||||
i: {
|
i: {
|
||||||
select: {
|
select: {
|
||||||
placeholder: 'Select',
|
placeholder: 'Select',
|
||||||
noMatch: 'No matching data'
|
noMatch: 'No matching data',
|
||||||
|
loading: 'Loading'
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
noDataText: 'No Data',
|
noDataText: 'No Data',
|
||||||
|
|
|
@ -2,7 +2,8 @@ export default {
|
||||||
i: {
|
i: {
|
||||||
select: {
|
select: {
|
||||||
placeholder: 'Seleccionar',
|
placeholder: 'Seleccionar',
|
||||||
noMatch: 'Sin coincidencias'
|
noMatch: 'Sin coincidencias',
|
||||||
|
loading: 'Cargando'
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
noDataText: 'Sin Datos',
|
noDataText: 'Sin Datos',
|
||||||
|
|
|
@ -2,7 +2,8 @@ export default {
|
||||||
i: {
|
i: {
|
||||||
select: {
|
select: {
|
||||||
placeholder: '選んでください',
|
placeholder: '選んでください',
|
||||||
noMatch: 'マッチするデータなし'
|
noMatch: 'マッチするデータなし',
|
||||||
|
loading: 'ロード中'
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
noDataText: 'データなし',
|
noDataText: 'データなし',
|
||||||
|
|
|
@ -2,7 +2,8 @@ export default {
|
||||||
i: {
|
i: {
|
||||||
select: {
|
select: {
|
||||||
placeholder: 'Seç',
|
placeholder: 'Seç',
|
||||||
noMatch: 'Eşleşen veri yok'
|
noMatch: 'Eşleşen veri yok',
|
||||||
|
loading: 'yükleme'
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
noDataText: 'Veri Yok',
|
noDataText: 'Veri Yok',
|
||||||
|
|
|
@ -2,7 +2,8 @@ export default {
|
||||||
i: {
|
i: {
|
||||||
select: {
|
select: {
|
||||||
placeholder: '请选择',
|
placeholder: '请选择',
|
||||||
noMatch: '无匹配数据'
|
noMatch: '无匹配数据',
|
||||||
|
loading: '加载中'
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
noDataText: '暂无数据',
|
noDataText: '暂无数据',
|
||||||
|
|
|
@ -2,7 +2,8 @@ export default {
|
||||||
i: {
|
i: {
|
||||||
select: {
|
select: {
|
||||||
placeholder: '請選擇',
|
placeholder: '請選擇',
|
||||||
noMatch: '無匹配數據'
|
noMatch: '無匹配數據',
|
||||||
|
loading: '加載中'
|
||||||
},
|
},
|
||||||
table: {
|
table: {
|
||||||
noDataText: '暫無數據',
|
noDataText: '暫無數據',
|
||||||
|
|
|
@ -174,6 +174,10 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: @btn-disable-color;
|
color: @btn-disable-color;
|
||||||
}
|
}
|
||||||
|
&-loading{
|
||||||
|
text-align: center;
|
||||||
|
color: @btn-disable-color;
|
||||||
|
}
|
||||||
|
|
||||||
&-multiple .@{css-prefix}tag{
|
&-multiple .@{css-prefix}tag{
|
||||||
margin: 3px 4px 2px 0;
|
margin: 3px 4px 2px 0;
|
||||||
|
|
Loading…
Add table
Reference in a new issue