2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-19 09:50:33 +03:00

- add filter function prop

- rename `filterFunction` to `filterComparator`
- add dev example using fuse.js
- update jsdocs
- update tests
This commit is contained in:
Jeff
2018-01-12 22:39:04 -08:00
parent 81a99536f7
commit 21ec385718
4 changed files with 73 additions and 37 deletions
+7 -3
View File
@@ -40,17 +40,21 @@
<v-select placeholder="search github.." label="full_name" @search="search" :options="ajaxRes"></v-select> <v-select placeholder="search github.." label="full_name" @search="search" :options="ajaxRes"></v-select>
<v-select placeholder="custom option template" :options="options" multiple> <v-select placeholder="custom option template" :options="options" multiple>
<template slot="selected-option" scope="option"> <template slot="selected-option" scope="option">
<img :src='"https://www.kidlink.org/icons/f0-" + option.value.toLowerCase() + ".gif"'/>
{{option.label}} {{option.label}}
</template> </template>
<template slot="option" scope="option"> <template slot="option" scope="option">
<img :src='"https://www.kidlink.org/icons/f0-" + option.value.toLowerCase() + ".gif"'/>
{{option.label}} ({{option.value}}) {{option.label}} ({{option.value}})
</template> </template>
</v-select> </v-select>
<v-select placeholder="disabled" disabled value="disabled"></v-select> <v-select placeholder="disabled" disabled value="disabled"></v-select>
<v-select placeholder="disabled multiple" disabled multiple :value="['disabled', 'multiple']"></v-select> <v-select placeholder="disabled multiple" disabled multiple :value="['disabled', 'multiple']"></v-select>
<v-select placeholder="filterable=false, @search=searchPeople" label="first_name" :filterable="false" @search="searchPeople" :options="people"></v-select> <v-select placeholder="filterable=false, @search=searchPeople" label="first_name" :filterable="false" @search="searchPeople" :options="people"></v-select>
<v-select placeholder="filtering with fuse.js" label="title" :options="fuseSearchOptions" :filter="fuseSearch">
<template slot="option" scope="option">
<strong>{{ option.title }}</strong><br>
<em>{{ `${option.author.firstName} ${option.author.lastName}` }}</em>
</template>
</v-select>
</div> </div>
</body> </body>
+43 -30
View File
@@ -522,34 +522,6 @@
} }
}, },
/**
* 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
}
},
filter: {
"type": Function,
default(vm) {
return vm.mutableOptions.filter((option) => {
let label = vm.getOptionLabel(option)
if (typeof label === 'number') {
label = label.toString()
}
return this.filterFunction(option, label, vm.search)
});
}
},
/** /**
* An optional callback function that is called each time the selected * An optional callback function that is called each time the selected
* value(s) change. When integrating with Vuex, use this callback to trigger * value(s) change. When integrating with Vuex, use this callback to trigger
@@ -603,6 +575,44 @@
default: true default: true
}, },
/**
* Callback to determine if the provided option
* should match the current search text.
* @type {Function}
* @param {Object || String} option
* @param {String} label
* @param {String} search
* @return {Boolean}
*/
filterComparator: {
type: Function,
default(option, label, search) {
return (label || '').toLowerCase().indexOf(search.toLowerCase()) > -1
}
},
/**
* Callback to filter results when
* search text is provided.
* @type {Function}
* @param {Array} list of options
* @param {String} search text
* @param {Object} vSelect instance
* @return {Boolean}
*/
filter: {
"type": Function,
default(options, search) {
return options.filter((option) => {
let label = this.getOptionLabel(option)
if (typeof label === 'number') {
label = label.toString()
}
return this.filterComparator(option, label, search)
});
}
},
/** /**
* User defined function for adding Options * User defined function for adding Options
* @type {Function} * @type {Function}
@@ -995,8 +1005,11 @@
* @return {array} * @return {array}
*/ */
filteredOptions() { filteredOptions() {
let options = this.search.length ? this.filter(this) : this.mutableOptions; if (!this.filterable && !this.taggable) {
if (this.taggable && !this.optionExists(this.search)) { return this.mutableOptions.slice()
}
let options = this.search.length ? this.filter(this.mutableOptions, this.search, this) : this.mutableOptions;
if (this.taggable && this.search.length && !this.optionExists(this.search)) {
options.unshift(this.search) options.unshift(this.search)
} }
return options return options
+4 -3
View File
@@ -1,9 +1,9 @@
import Vue from 'vue' import Vue from 'vue'
import Fuse from 'fuse.js' import Fuse from 'fuse.js'
import debounce from 'lodash/debounce'
import resource from 'vue-resource' import resource from 'vue-resource'
import vSelect from './components/Select.vue' import vSelect from './components/Select.vue'
import countries from 'docs/data/advanced.js' import countries from 'docs/data/advanced.js'
import debounce from 'lodash/debounce'
import fuseSearchOptions from './fuseSearchOptions' import fuseSearchOptions from './fuseSearchOptions'
Vue.use(resource) Vue.use(resource)
@@ -20,6 +20,7 @@ new Vue({
value: null, value: null,
options: countries, options: countries,
ajaxRes: [], ajaxRes: [],
people: [],
fuseSearchOptions fuseSearchOptions
}, },
methods: { methods: {
@@ -43,8 +44,8 @@ new Vue({
loading(false) loading(false)
}) })
}, 250), }, 250),
fuse({mutableOptions, search}) { fuseSearch(options, search) {
return new Fuse(mutableOptions, { return new Fuse(options, {
keys: ['title', 'author.firstName', 'author.lastName'], keys: ['title', 'author.firstName', 'author.lastName'],
}).search(search); }).search(search);
} }
+19 -1
View File
@@ -322,7 +322,7 @@ describe('Select.vue', () => {
expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify([{label: 'Bar', value: 'bar'}, {label: 'Baz', value: 'baz'}])) 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', ()=>{ it('can determine if a given option should match the current search text', () => {
const vm = new Vue({ const vm = new Vue({
template: `<div><v-select ref="select" :filterFunction="customFn" :options="[{label: 'Aoo', value: 'foo'}, {label: 'Bar', value: 'bar'}, {label: 'Baz', value: 'baz'}]" v-model="value"></v-select></div>`, template: `<div><v-select ref="select" :filterFunction="customFn" :options="[{label: 'Aoo', value: 'foo'}, {label: 'Bar', value: 'bar'}, {label: 'Baz', value: 'baz'}]" v-model="value"></v-select></div>`,
data: {value: 'foo'}, data: {value: 'foo'},
@@ -333,6 +333,23 @@ describe('Select.vue', () => {
vm.$refs.select.search = 'a' vm.$refs.select.search = 'a'
expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify([{label: 'Aoo', value: 'foo'}])) expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify([{label: 'Aoo', value: 'foo'}]))
}) })
it('can use a custom filtering method', () => {
const vm = new Vue({
template: `<div><v-select ref="select" :filter="customFn" :options="options" v-model="value"></v-select></div>`,
data: {
options: ['foo','bar','baz'],
value: 'foo'
},
methods:{
customFn(options, search, vm) {
return options.filter(option => option.indexOf(search) > 0)
}
}
}).$mount()
vm.$refs.select.search = 'a'
expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify(['bar','baz']))
})
}) })
describe('Toggling Dropdown', () => { describe('Toggling Dropdown', () => {
@@ -780,6 +797,7 @@ describe('Select.vue', () => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select :options="[{}]"></v-select></div>', template: '<div><v-select :options="[{}]"></v-select></div>',
}).$mount() }).$mount()
vm.$children[0].open = true
Vue.nextTick(() => { Vue.nextTick(() => {
expect(console.warn).toHaveBeenCalledWith( 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 {}.' +