From 7dbde804d8a85099c77dbbbf80133eec5a508af8 Mon Sep 17 00:00:00 2001 From: Sergio Crisostomo Date: Tue, 8 May 2018 12:47:03 +0200 Subject: [PATCH 1/6] add on-clear event --- examples/routers/select.vue | 21 +++++++++++++-------- src/components/select/select-head.vue | 5 ++++- src/components/select/select.vue | 2 ++ 3 files changed, 19 insertions(+), 9 deletions(-) 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: { diff --git a/src/components/select/select.vue b/src/components/select/select.vue index 6ca51b3d..709115c4 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" /> @@ -382,6 +383,7 @@ } }, clearSingleSelect(){ // PUBLIC API + this.$emit('on-clear'); if (this.clearable) this.values = []; }, getOptionData(value){ From 31788df30b739d279c9b994fad97ecf52f68b5dd Mon Sep 17 00:00:00 2001 From: Sergio Crisostomo Date: Tue, 8 May 2018 14:23:49 +0200 Subject: [PATCH 2/6] Normalise behaviour when opening select with selected option present in options --- src/components/select/select.vue | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/components/select/select.vue b/src/components/select/select.vue index 709115c4..a202cf03 100644 --- a/src/components/select/select.vue +++ b/src/components/select/select.vue @@ -122,6 +122,8 @@ }; }; + const ANIMATION_TIMEOUT = 300; + export default { name: 'iSelect', mixins: [ Emitter, Locale ], @@ -230,6 +232,7 @@ slotOptions: this.$slots.default, caretPosition: -1, lastRemoteQuery: '', + unchangedQuery: true, hasExpectedValue: false, preventRemoteCall: false, }; @@ -261,6 +264,10 @@ [`${prefixCls}-selection-focused`]: this.isFocused }; }, + queryStringMatchesSelectedOption(){ + const selectedOptions = this.values[0]; + return selectedOptions && !this.multiple && this.unchangedQuery && this.query === selectedOptions.value; + }, localeNotFoundText () { if (typeof this.notFoundText === 'undefined') { return this.t('i.select.noMatch'); @@ -425,6 +432,7 @@ }, validateOption({elm, propsData}){ + if (this.queryStringMatchesSelectedOption) return true; const value = propsData.value; const label = propsData.label || ''; const textContent = elm && elm.textContent || ''; @@ -446,6 +454,7 @@ }, hideMenu () { this.toggleMenu(null, false); + setTimeout(() => this.unchangedQuery = true, ANIMATION_TIMEOUT); }, onClickOutside(event){ if (this.visible) { @@ -469,6 +478,7 @@ } }, reset(){ + this.unchangedQuery = true; this.values = []; }, handleKeydown (e) { @@ -553,6 +563,7 @@ this.isFocused = true; // so we put back focus after clicking with mouse on option elements } else { + this.query = option.value; this.values = [option]; this.lastRemoteQuery = ''; this.hideMenu(); @@ -565,6 +576,7 @@ this.broadcast('Drop', 'on-update-popper'); }, onQueryChange(query) { + this.unchangedQuery = false; this.query = query; if (this.query.length > 0) this.visible = true; }, From c3304bce349cb652f68b56a68360bbe3fd902f2b Mon Sep 17 00:00:00 2001 From: Sergio Crisostomo Date: Fri, 11 May 2018 08:45:14 +0200 Subject: [PATCH 3/6] correct unchangedQuery and queryStringMatchesSelectedOption logic and --- src/components/select/select-head.vue | 1 + src/components/select/select.vue | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/select/select-head.vue b/src/components/select/select-head.vue index 3d54d643..4165e5f5 100644 --- a/src/components/select/select-head.vue +++ b/src/components/select/select-head.vue @@ -182,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 a202cf03..0cf9a001 100644 --- a/src/components/select/select.vue +++ b/src/components/select/select.vue @@ -266,7 +266,7 @@ }, queryStringMatchesSelectedOption(){ const selectedOptions = this.values[0]; - return selectedOptions && !this.multiple && this.unchangedQuery && this.query === selectedOptions.value; + return selectedOptions && !this.multiple && this.unchangedQuery && this.query === selectedOptions.label; }, localeNotFoundText () { if (typeof this.notFoundText === 'undefined') { @@ -391,6 +391,7 @@ }, clearSingleSelect(){ // PUBLIC API this.$emit('on-clear'); + this.hideMenu(); if (this.clearable) this.values = []; }, getOptionData(value){ @@ -437,7 +438,8 @@ 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(); + return stringValues.toLowerCase().includes(query); }, toggleMenu (e, force) { @@ -563,7 +565,7 @@ this.isFocused = true; // so we put back focus after clicking with mouse on option elements } else { - this.query = option.value; + this.query = option.label; this.values = [option]; this.lastRemoteQuery = ''; this.hideMenu(); @@ -576,9 +578,9 @@ this.broadcast('Drop', 'on-update-popper'); }, onQueryChange(query) { - this.unchangedQuery = false; + 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) { From 1376a01a72229593c33806128bedd21aaafc05bd Mon Sep 17 00:00:00 2001 From: Sergio Crisostomo Date: Fri, 11 May 2018 10:37:18 +0200 Subject: [PATCH 4/6] Emit on-open-change events --- src/components/select/select.vue | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/select/select.vue b/src/components/select/select.vue index 0cf9a001..39928952 100644 --- a/src/components/select/select.vue +++ b/src/components/select/select.vue @@ -684,6 +684,9 @@ if (this.slotOptions && this.slotOptions.length === 0){ this.query = ''; } + }, + visible(state){ + this.$emit('on-open-change', state); } } }; From 52cfcd662b78ca2f550c00c35686920dcc13d1b8 Mon Sep 17 00:00:00 2001 From: Sergio Crisostomo Date: Fri, 11 May 2018 10:37:01 +0200 Subject: [PATCH 5/6] Keep last selected option index --- src/components/select/select.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/select/select.vue b/src/components/select/select.vue index 39928952..18728944 100644 --- a/src/components/select/select.vue +++ b/src/components/select/select.vue @@ -446,7 +446,6 @@ if (this.disabled || this.autoComplete) { return false; } - this.focusIndex = -1; this.visible = typeof force !== 'undefined' ? force : !this.visible; if (this.visible){ @@ -571,6 +570,11 @@ 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()); From 5266c9054b6a85ea1b86372bde592c23933c4b13 Mon Sep 17 00:00:00 2001 From: Sergio Crisostomo Date: Fri, 11 May 2018 10:52:58 +0200 Subject: [PATCH 6/6] Trim label so we can compare and use label better --- src/components/select/select.vue | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/components/select/select.vue b/src/components/select/select.vue index 18728944..c79bb524 100644 --- a/src/components/select/select.vue +++ b/src/components/select/select.vue @@ -266,7 +266,9 @@ }, queryStringMatchesSelectedOption(){ const selectedOptions = this.values[0]; - return selectedOptions && !this.multiple && this.unchangedQuery && this.query === selectedOptions.label; + 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') { @@ -438,7 +440,7 @@ const label = propsData.label || ''; const textContent = elm && elm.textContent || ''; const stringValues = JSON.stringify([value, label, textContent]); - const query = this.query.toLowerCase(); + const query = this.query.toLowerCase().trim(); return stringValues.toLowerCase().includes(query); }, @@ -564,7 +566,7 @@ this.isFocused = true; // so we put back focus after clicking with mouse on option elements } else { - this.query = option.label; + this.query = String(option.label).trim(); this.values = [option]; this.lastRemoteQuery = ''; this.hideMenu(); @@ -652,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;