diff --git a/examples/routers/select.vue b/examples/routers/select.vue index 6beda00f..cc34197c 100644 --- a/examples/routers/select.vue +++ b/examples/routers/select.vue @@ -671,16 +671,16 @@ @@ -165,6 +165,9 @@ if (this.filterable && e.target === this.$el){ this.$refs.input.focus(); } + }, + onClear(){ + this.$emit('on-clear'); } }, watch: { @@ -179,6 +182,7 @@ // #982 if (typeof value === 'undefined' || value === '' || value === null) this.query = ''; else this.query = value.label; + this.$nextTick(() => this.preventRemoteCall = false); // this should be after the query change setter above }, query (val) { if (this.preventRemoteCall) { diff --git a/src/components/select/select.vue b/src/components/select/select.vue index 6ca51b3d..c79bb524 100644 --- a/src/components/select/select.vue +++ b/src/components/select/select.vue @@ -42,6 +42,7 @@ @on-query-change="onQueryChange" @on-input-focus="isFocused = true" @on-input-blur="isFocused = false" + @on-clear="clearSingleSelect" /> @@ -121,6 +122,8 @@ }; }; + const ANIMATION_TIMEOUT = 300; + export default { name: 'iSelect', mixins: [ Emitter, Locale ], @@ -229,6 +232,7 @@ slotOptions: this.$slots.default, caretPosition: -1, lastRemoteQuery: '', + unchangedQuery: true, hasExpectedValue: false, preventRemoteCall: false, }; @@ -260,6 +264,12 @@ [`${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 () { if (typeof this.notFoundText === 'undefined') { return this.t('i.select.noMatch'); @@ -382,6 +392,8 @@ } }, clearSingleSelect(){ // PUBLIC API + this.$emit('on-clear'); + this.hideMenu(); if (this.clearable) this.values = []; }, getOptionData(value){ @@ -423,18 +435,19 @@ }, validateOption({elm, propsData}){ + if (this.queryStringMatchesSelectedOption) return true; const value = propsData.value; const label = propsData.label || ''; const textContent = elm && elm.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) { if (this.disabled || this.autoComplete) { return false; } - this.focusIndex = -1; this.visible = typeof force !== 'undefined' ? force : !this.visible; if (this.visible){ @@ -444,6 +457,7 @@ }, hideMenu () { this.toggleMenu(null, false); + setTimeout(() => this.unchangedQuery = true, ANIMATION_TIMEOUT); }, onClickOutside(event){ if (this.visible) { @@ -467,6 +481,7 @@ } }, reset(){ + this.unchangedQuery = true; this.values = []; }, handleKeydown (e) { @@ -551,11 +566,17 @@ this.isFocused = true; // so we put back focus after clicking with mouse on option elements } else { + this.query = String(option.label).trim(); this.values = [option]; this.lastRemoteQuery = ''; this.hideMenu(); } + this.focusIndex = this.flatOptions.findIndex((opt) => { + if (!opt || !opt.componentOptions) return false; + return opt.componentOptions.propsData.value === option.value; + }); + if (this.filterable){ const inputField = this.$el.querySelector('input[type="text"]'); if (!this.autoComplete) this.$nextTick(() => inputField.focus()); @@ -563,8 +584,9 @@ this.broadcast('Drop', 'on-update-popper'); }, onQueryChange(query) { + if (query.length > 0 && query !== this.query) this.visible = true; this.query = query; - if (this.query.length > 0) this.visible = true; + this.unchangedQuery = this.visible; }, toggleHeaderFocus({type}){ if (this.disabled) { @@ -632,7 +654,7 @@ // restore query value in filterable single selects const [selectedOption] = this.values; 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) { this.preventRemoteCall = true; this.query = selectedLabel; @@ -668,6 +690,9 @@ if (this.slotOptions && this.slotOptions.length === 0){ this.query = ''; } + }, + visible(state){ + this.$emit('on-open-change', state); } } };