From 4247b4dfc12c9266a65213d2e12fd7282e8f22b4 Mon Sep 17 00:00:00 2001 From: meteorlxy Date: Sat, 26 Aug 2017 22:08:28 +0000 Subject: [PATCH 1/8] Combine #295 and #296 --- src/components/Select.vue | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/Select.vue b/src/components/Select.vue index 4dc46bf..9b86837 100644 --- a/src/components/Select.vue +++ b/src/components/Select.vue @@ -436,6 +436,9 @@ type: Function, default(option) { if (typeof option === 'object') { + if (!option.hasOwnProperty(this.label)) { + return console.warn(`[vue-select warn]: Label key "option.${this.label}" does not exist in options object.\nhttp://sagalbot.github.io/vue-select/#ex-labels`) + } if (this.label && option[this.label]) { return option[this.label] } @@ -847,12 +850,11 @@ */ filteredOptions() { let options = this.mutableOptions.filter((option) => { - if (typeof option === 'object' && option.hasOwnProperty(this.label)) { - return option[this.label].toLowerCase().indexOf(this.search.toLowerCase()) > -1 - } else if (typeof option === 'object' && !option.hasOwnProperty(this.label)) { - return console.warn(`[vue-select warn]: Label key "option.${this.label}" does not exist in options object.\nhttp://sagalbot.github.io/vue-select/#ex-labels`) + let label = this.getOptionLabel(option) + if (typeof label === 'number') { + label = label.toString() } - return option.toLowerCase().indexOf(this.search.toLowerCase()) > -1 + return label.toLowerCase().indexOf(this.search.toLowerCase()) > -1 }) if (this.taggable && this.search.length && !this.optionExists(this.search)) { options.unshift(this.search) From 04f77fedb2083269e8f707c4b703e4e0adf020ec Mon Sep 17 00:00:00 2001 From: meteorlxy Date: Sun, 27 Aug 2017 03:04:36 +0000 Subject: [PATCH 2/8] Add custom filter function --- src/components/Select.vue | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/components/Select.vue b/src/components/Select.vue index 9b86837..e72ec7a 100644 --- a/src/components/Select.vue +++ b/src/components/Select.vue @@ -446,6 +446,21 @@ return option; } }, + + /** + * Callback to filter the search result the label text. + * @type {Function} + * @param {Object || String} option + * @param {String} label + * @param {String} search + * @return {Boolean} + */ + filterFunction: { + type: Function, + default(option, label, search) { + return label.toLowerCase().indexOf(search.toLowerCase()) > -1 + } + }, /** * An optional callback function that is called each time the selected @@ -854,7 +869,7 @@ if (typeof label === 'number') { label = label.toString() } - return label.toLowerCase().indexOf(this.search.toLowerCase()) > -1 + return this.filterFunction(option, label, this.search) }) if (this.taggable && this.search.length && !this.optionExists(this.search)) { options.unshift(this.search) From 014c51d1e7f2ba0b546c5000ce8755a3db9b9f44 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 26 Oct 2017 12:16:54 -0400 Subject: [PATCH 3/8] Stylistic changes to getOptionLabel() default console.warn Split into multiple lines, included stringified defective option object. --- src/components/Select.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/Select.vue b/src/components/Select.vue index 430723f..dc5f3ff 100644 --- a/src/components/Select.vue +++ b/src/components/Select.vue @@ -470,7 +470,11 @@ default(option) { if (typeof option === 'object') { if (!option.hasOwnProperty(this.label)) { - return console.warn(`[vue-select warn]: Label key "option.${this.label}" does not exist in options object.\nhttp://sagalbot.github.io/vue-select/#ex-labels`) + return console.warn( + `[vue-select warn]: Label key "option.${this.label}" does not` + + ` exist in options object ${JSON.stringify(option)}.\n` + + 'http://sagalbot.github.io/vue-select/#ex-labels' + ) } if (this.label && option[this.label]) { return option[this.label] From 57c084dd8bb4d9c5de6747b149d253ef813cb0c0 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 26 Oct 2017 12:18:30 -0400 Subject: [PATCH 4/8] fallback truthiness check on option label In case getOptionLabel somehow returns undefined. Overkill, but inexpensive overkill. --- src/components/Select.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/Select.vue b/src/components/Select.vue index dc5f3ff..616d9d0 100644 --- a/src/components/Select.vue +++ b/src/components/Select.vue @@ -483,19 +483,19 @@ return option; } }, - + /** - * Callback to filter the search result the label text. - * @type {Function} - * @param {Object || String} option - * @param {String} label + * Callback to filter the search result the label text. + * @type {Function} + * @param {Object || String} option + * @param {String} label * @param {String} search * @return {Boolean} */ filterFunction: { type: Function, default(option, label, search) { - return label.toLowerCase().indexOf(search.toLowerCase()) > -1 + return (label || '').toLowerCase().indexOf(search.toLowerCase()) > -1 } }, From a7562402c7c329f76f5b07e6399ba4fc0e5e691a Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 26 Oct 2017 12:19:23 -0400 Subject: [PATCH 5/8] Modified spec to include warning of defective options objects --- test/unit/specs/Select.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/specs/Select.spec.js b/test/unit/specs/Select.spec.js index d08d9e2..cff7c8d 100644 --- a/test/unit/specs/Select.spec.js +++ b/test/unit/specs/Select.spec.js @@ -761,7 +761,7 @@ describe('Select.vue', () => { }).$mount() Vue.nextTick(() => { expect(console.warn).toHaveBeenCalledWith( - '[vue-select warn]: Label key "option.label" does not exist in options object.' + + '[vue-select warn]: Label key "option.label" does not exist in options object {}.' + '\nhttp://sagalbot.github.io/vue-select/#ex-labels' ) done() From 10e8516639828cd4d6d8420756f6ef086e5b3279 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 26 Oct 2017 12:20:04 -0400 Subject: [PATCH 6/8] Killed production tip in spec --- test/unit/specs/Select.spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/specs/Select.spec.js b/test/unit/specs/Select.spec.js index cff7c8d..05cbdaf 100644 --- a/test/unit/specs/Select.spec.js +++ b/test/unit/specs/Select.spec.js @@ -4,7 +4,7 @@ import Vue from 'vue' import vSelect from 'src/components/Select.vue' import pointerScroll from 'src/mixins/pointerScroll.js' - +Vue.config.productionTip = false // http://vue-loader.vuejs.org/en/workflow/testing-with-mocks.html const Mock = require('!!vue?inject!src/components/Select.vue') @@ -1189,11 +1189,11 @@ describe('Select.vue', () => { options: ['one', 'two', 'three'] } }).$mount() - + vm.$children[0].open = true vm.$refs.select.search = "t" expect(vm.$refs.select.search).toEqual('t') - + vm.$children[0].onSearchBlur() Vue.nextTick(() => { expect(vm.$refs.select.search).toEqual('') From e30a000dda4d59074d2c378a3975eaefbb2abbe0 Mon Sep 17 00:00:00 2001 From: Unknown Date: Thu, 26 Oct 2017 12:26:00 -0400 Subject: [PATCH 7/8] valueAsArray to handle passed arrays In the test suite sometimes a mutableValue array is passed when `multiple == false`. Using [].concat rather than an array literall allows valueAsArray to handle these cases. [].concat could handle the case when `multiple == true` as well. --- src/components/Select.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Select.vue b/src/components/Select.vue index 616d9d0..6d00d75 100644 --- a/src/components/Select.vue +++ b/src/components/Select.vue @@ -952,7 +952,7 @@ if (this.multiple) { return this.mutableValue } else if (this.mutableValue) { - return [this.mutableValue] + return [].concat(this.mutableValue) } return [] From 47750233ba7342de341e85af7b5d1492e9a035a8 Mon Sep 17 00:00:00 2001 From: Steven Kalt Date: Thu, 26 Oct 2017 12:45:12 -0400 Subject: [PATCH 8/8] added test of custom filter function --- test/unit/specs/Select.spec.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/unit/specs/Select.spec.js b/test/unit/specs/Select.spec.js index 05cbdaf..fea4e78 100644 --- a/test/unit/specs/Select.spec.js +++ b/test/unit/specs/Select.spec.js @@ -312,6 +312,18 @@ describe('Select.vue', () => { vm.$refs.select.search = 'ba' expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify([{label: 'Bar', value: 'bar'}, {label: 'Baz', value: 'baz'}])) }) + + it('can use a custom filterFunction passed via props', ()=>{ + const vm = new Vue({ + template: `
`, + data: {value: 'foo'}, + methods:{ + customFn: (option, label, search) => label.match(new RegExp('^' + search, 'i')) + } + }).$mount() + vm.$refs.select.search = 'a' + expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify([{label: 'Aoo', value: 'foo'}])) + }) }) describe('Toggling Dropdown', () => {