Merge pull request #3579 from SergioCrisostomo/refactor-select

more select improvements
This commit is contained in:
Aresn 2018-05-11 17:03:26 +08:00 committed by GitHub
commit 930b85838e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 13 deletions

View file

@ -671,16 +671,16 @@
<template> <template>
<div> <div>
<Select v-model="model1" size="small" style="width:200px;"> <Select v-model="model1" size="small" style="width:200px;" >
<Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option> <Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option>
</Select> </Select>
<Select v-model="model10" size="small" multiple style="width:260px"> <Select v-model="model10" size="small" multiple style="width:260px" >
<Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option> <Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option>
</Select> </Select>
<br><br> <br><br>
<Select v-model="model1" size="large" style="width:200px"> <Select v-model="model1" size="large" style="width:200px" clearable @on-clear="onClear">
<Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option> <Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option>
</Select> </Select>
<Select v-model="model10" size="large" multiple style="width:260px"> <Select v-model="model10" size="large" multiple style="width:260px">
@ -761,6 +761,11 @@
model10: [], model10: [],
model11: [] model11: []
} }
},
methods: {
onClear(){
console.log('onClear');
}
} }
} }
</script> </script>

View file

@ -25,7 +25,7 @@
@blur="onInputFocus" @blur="onInputFocus"
ref="input"> ref="input">
<Icon type="ios-close" :class="[prefixCls + '-arrow']" v-if="resetSelect" @click.native.stop="resetSelect"></Icon> <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-if="resetSelect" @click.native.stop="onClear"></Icon>
<Icon type="arrow-down-b" :class="[prefixCls + '-arrow']" v-if="!resetSelect && !remote && !disabled"></Icon> <Icon type="arrow-down-b" :class="[prefixCls + '-arrow']" v-if="!resetSelect && !remote && !disabled"></Icon>
</div> </div>
</template> </template>
@ -165,6 +165,9 @@
if (this.filterable && e.target === this.$el){ if (this.filterable && e.target === this.$el){
this.$refs.input.focus(); this.$refs.input.focus();
} }
},
onClear(){
this.$emit('on-clear');
} }
}, },
watch: { watch: {
@ -179,6 +182,7 @@
// #982 // #982
if (typeof value === 'undefined' || value === '' || value === null) this.query = ''; if (typeof value === 'undefined' || value === '' || value === null) this.query = '';
else this.query = value.label; else this.query = value.label;
this.$nextTick(() => this.preventRemoteCall = false); // this should be after the query change setter above
}, },
query (val) { query (val) {
if (this.preventRemoteCall) { if (this.preventRemoteCall) {

View file

@ -42,6 +42,7 @@
@on-query-change="onQueryChange" @on-query-change="onQueryChange"
@on-input-focus="isFocused = true" @on-input-focus="isFocused = true"
@on-input-blur="isFocused = false" @on-input-blur="isFocused = false"
@on-clear="clearSingleSelect"
/> />
</slot> </slot>
</div> </div>
@ -121,6 +122,8 @@
}; };
}; };
const ANIMATION_TIMEOUT = 300;
export default { export default {
name: 'iSelect', name: 'iSelect',
mixins: [ Emitter, Locale ], mixins: [ Emitter, Locale ],
@ -229,6 +232,7 @@
slotOptions: this.$slots.default, slotOptions: this.$slots.default,
caretPosition: -1, caretPosition: -1,
lastRemoteQuery: '', lastRemoteQuery: '',
unchangedQuery: true,
hasExpectedValue: false, hasExpectedValue: false,
preventRemoteCall: false, preventRemoteCall: false,
}; };
@ -260,6 +264,12 @@
[`${prefixCls}-selection-focused`]: this.isFocused [`${prefixCls}-selection-focused`]: this.isFocused
}; };
}, },
queryStringMatchesSelectedOption(){
const selectedOptions = this.values[0];
if (!selectedOptions) return false;
const [query, label] = [this.query, selectedOptions.label].map(str => (str || '').trim());
return !this.multiple && this.unchangedQuery && query === label;
},
localeNotFoundText () { localeNotFoundText () {
if (typeof this.notFoundText === 'undefined') { if (typeof this.notFoundText === 'undefined') {
return this.t('i.select.noMatch'); return this.t('i.select.noMatch');
@ -382,6 +392,8 @@
} }
}, },
clearSingleSelect(){ // PUBLIC API clearSingleSelect(){ // PUBLIC API
this.$emit('on-clear');
this.hideMenu();
if (this.clearable) this.values = []; if (this.clearable) this.values = [];
}, },
getOptionData(value){ getOptionData(value){
@ -423,18 +435,19 @@
}, },
validateOption({elm, propsData}){ validateOption({elm, propsData}){
if (this.queryStringMatchesSelectedOption) return true;
const value = propsData.value; const value = propsData.value;
const label = propsData.label || ''; const label = propsData.label || '';
const textContent = elm && elm.textContent || ''; const textContent = elm && elm.textContent || '';
const stringValues = JSON.stringify([value, label, textContent]); const stringValues = JSON.stringify([value, label, textContent]);
return stringValues.toLowerCase().includes(this.query.toLowerCase()); const query = this.query.toLowerCase().trim();
return stringValues.toLowerCase().includes(query);
}, },
toggleMenu (e, force) { toggleMenu (e, force) {
if (this.disabled || this.autoComplete) { if (this.disabled || this.autoComplete) {
return false; return false;
} }
this.focusIndex = -1;
this.visible = typeof force !== 'undefined' ? force : !this.visible; this.visible = typeof force !== 'undefined' ? force : !this.visible;
if (this.visible){ if (this.visible){
@ -444,6 +457,7 @@
}, },
hideMenu () { hideMenu () {
this.toggleMenu(null, false); this.toggleMenu(null, false);
setTimeout(() => this.unchangedQuery = true, ANIMATION_TIMEOUT);
}, },
onClickOutside(event){ onClickOutside(event){
if (this.visible) { if (this.visible) {
@ -467,6 +481,7 @@
} }
}, },
reset(){ reset(){
this.unchangedQuery = true;
this.values = []; this.values = [];
}, },
handleKeydown (e) { handleKeydown (e) {
@ -551,11 +566,17 @@
this.isFocused = true; // so we put back focus after clicking with mouse on option elements this.isFocused = true; // so we put back focus after clicking with mouse on option elements
} else { } else {
this.query = String(option.label).trim();
this.values = [option]; this.values = [option];
this.lastRemoteQuery = ''; this.lastRemoteQuery = '';
this.hideMenu(); this.hideMenu();
} }
this.focusIndex = this.flatOptions.findIndex((opt) => {
if (!opt || !opt.componentOptions) return false;
return opt.componentOptions.propsData.value === option.value;
});
if (this.filterable){ if (this.filterable){
const inputField = this.$el.querySelector('input[type="text"]'); const inputField = this.$el.querySelector('input[type="text"]');
if (!this.autoComplete) this.$nextTick(() => inputField.focus()); if (!this.autoComplete) this.$nextTick(() => inputField.focus());
@ -563,8 +584,9 @@
this.broadcast('Drop', 'on-update-popper'); this.broadcast('Drop', 'on-update-popper');
}, },
onQueryChange(query) { onQueryChange(query) {
if (query.length > 0 && query !== this.query) this.visible = true;
this.query = query; this.query = query;
if (this.query.length > 0) this.visible = true; this.unchangedQuery = this.visible;
}, },
toggleHeaderFocus({type}){ toggleHeaderFocus({type}){
if (this.disabled) { if (this.disabled) {
@ -632,7 +654,7 @@
// restore query value in filterable single selects // restore query value in filterable single selects
const [selectedOption] = this.values; const [selectedOption] = this.values;
if (selectedOption && this.filterable && !this.multiple && !focused){ if (selectedOption && this.filterable && !this.multiple && !focused){
const selectedLabel = selectedOption.label || selectedOption.value; const selectedLabel = String(selectedOption.label || selectedOption.value).trim();
if (selectedLabel && this.query !== selectedLabel) { if (selectedLabel && this.query !== selectedLabel) {
this.preventRemoteCall = true; this.preventRemoteCall = true;
this.query = selectedLabel; this.query = selectedLabel;
@ -668,6 +690,9 @@
if (this.slotOptions && this.slotOptions.length === 0){ if (this.slotOptions && this.slotOptions.length === 0){
this.query = ''; this.query = '';
} }
},
visible(state){
this.$emit('on-open-change', state);
} }
} }
}; };