Select support remote search

This commit is contained in:
梁灏 2017-05-05 14:20:46 +08:00
parent 28587238de
commit 01b54e3021
9 changed files with 167 additions and 51 deletions

View file

@ -1,8 +1,9 @@
<template>
<div style="width: 200px;margin: 100px;">
<i-select v-model="model" filterable clearable style="width:200px">
<i-option :value="option.value" v-for="option in options" :key="option">{{option.label}}</i-option>
<i-select v-model="model" filterable remote :remote-method="remoteMethod" :loading="loading" clearable style="width:200px">
<i-option v-for="option in options" :value="option.value" :key="option">{{option.label}}</i-option>
</i-select>
<!--<Button @click="handleAdd">+</Button>-->
</div>
</template>
@ -10,26 +11,85 @@
export default {
data () {
return {
model: 1,
model: '',
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 () {
this.options = [{
label: '全部',
value: 0
},{
label: '苹果',
value: 1
},{
label: '香蕉',
value: 2
},{
label: '西瓜',
value: 3
}];
this.options = [
// {
// label: '',
// value: 0
// },{
// label: '',
// value: 1
// },{
// label: '',
// value: 2
// },{
// 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>

View file

@ -22,12 +22,16 @@
@keydown.delete="handleInputDelete"
ref="input">
<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>
<transition :name="transitionName">
<Drop v-show="visible" :placement="placement" ref="dropdown">
<ul v-show="notFound" :class="[prefixCls + '-not-found']"><li>{{ localeNotFoundText }}</li></ul>
<ul v-show="!notFound" :class="[prefixCls + '-dropdown-list']" ref="options"><slot></slot></ul>
<Drop v-show="(visible && options.length) ||
(visible && !options.length && loading) ||
(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>
</transition>
</div>
@ -74,6 +78,20 @@
filterMethod: {
type: Function
},
remote: {
type: Boolean,
default: false
},
remoteMethod: {
type: Function
},
loading: {
type: Boolean,
default: false
},
loadingText: {
type: String
},
size: {
validator (value) {
return oneOf(value, ['small', 'large', 'default']);
@ -103,6 +121,7 @@
selectedMultiple: [],
focusIndex: 0,
query: '',
selectToChangeQuery: false, // when select an option, set this first and set query, because query is watching, it will emit event
inputLength: 20,
notFound: 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;
}
},
localeLoadingText () {
if (this.loadingText === undefined) {
return this.t('i.select.loading');
} else {
return this.loadingText;
}
},
transitionName () {
return this.placement === 'bottom' ? 'slide-up' : 'slide-down';
}
@ -187,15 +213,18 @@
},
// find option component
findChild (cb) {
const _this = this;
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);
});
_this.$nextTick(() => {
child.$children.forEach((innerChild) => {
find(innerChild, cb);
});
})
}
};
@ -228,8 +257,10 @@
this.options = options;
if (init) {
this.updateSingleSelected(true, slot);
this.updateMultipleSelected(true, slot);
if (!this.remote) {
this.updateSingleSelected(true, slot);
this.updateMultipleSelected(true, slot);
}
}
},
updateSingleSelected (init = false, slot = false) {
@ -535,18 +566,22 @@
document.addEventListener('keydown', this.handleKeydown);
this.$on('append', () => {
this.modelToQuery();
this.$nextTick(() => {
this.broadcastQuery('');
});
if (!this.remote) {
this.modelToQuery();
this.$nextTick(() => {
this.broadcastQuery('');
});
}
this.slotChange();
this.updateOptions(true, true);
});
this.$on('remove', () => {
this.modelToQuery();
this.$nextTick(() => {
this.broadcastQuery('');
});
if (!this.remote) {
this.modelToQuery();
this.$nextTick(() => {
this.broadcastQuery('');
});
}
this.slotChange();
this.updateOptions(true, true);
});
@ -565,6 +600,7 @@
}
if (this.filterable) {
this.selectToChangeQuery = true;
this.query = '';
this.$refs.input.focus();
}
@ -574,6 +610,7 @@
if (this.filterable) {
this.findChild((child) => {
if (child.value === value) {
this.selectToChangeQuery = true;
this.query = child.label === undefined ? child.searchLabel : child.label;
}
});
@ -625,20 +662,29 @@
}
},
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.findChild((child) => {
if (!child.hidden) {
is_hidden = false;
}
this.$nextTick(() => {
this.findChild((child) => {
if (!child.hidden) {
is_hidden = false;
}
});
this.notFound = is_hidden;
});
this.notFound = is_hidden;
});
}
this.selectToChangeQuery = false;
this.broadcast('Drop', 'on-update-popper');
}
}

View file

@ -2,7 +2,8 @@ export default {
i: {
select: {
placeholder: 'Select',
noMatch: 'No matching data'
noMatch: 'No matching data',
loading: 'Loading'
},
table: {
noDataText: 'No Data',

View file

@ -2,7 +2,8 @@ export default {
i: {
select: {
placeholder: 'Seleccionar',
noMatch: 'Sin coincidencias'
noMatch: 'Sin coincidencias',
loading: 'Cargando'
},
table: {
noDataText: 'Sin Datos',

View file

@ -2,7 +2,8 @@ export default {
i: {
select: {
placeholder: '選んでください',
noMatch: 'マッチするデータなし'
noMatch: 'マッチするデータなし',
loading: 'ロード中'
},
table: {
noDataText: 'データなし',

View file

@ -2,7 +2,8 @@ export default {
i: {
select: {
placeholder: 'Seç',
noMatch: 'Eşleşen veri yok'
noMatch: 'Eşleşen veri yok',
loading: 'yükleme'
},
table: {
noDataText: 'Veri Yok',

View file

@ -2,7 +2,8 @@ export default {
i: {
select: {
placeholder: '请选择',
noMatch: '无匹配数据'
noMatch: '无匹配数据',
loading: '加载中'
},
table: {
noDataText: '暂无数据',

View file

@ -2,7 +2,8 @@ export default {
i: {
select: {
placeholder: '請選擇',
noMatch: '無匹配數據'
noMatch: '無匹配數據',
loading: '加載中'
},
table: {
noDataText: '暫無數據',

View file

@ -174,6 +174,10 @@
text-align: center;
color: @btn-disable-color;
}
&-loading{
text-align: center;
color: @btn-disable-color;
}
&-multiple .@{css-prefix}tag{
margin: 3px 4px 2px 0;