mirror of
https://github.com/tenrok/vue-select.git
synced 2026-05-17 02:29:37 +03:00
add custom label prop
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
# vue-select [](https://travis-ci.org/sagalbot/vue-select)
|
||||
|
||||
Rather than bringing in jQuery just to use Select2 or Chosen, this Vue.js component provides similar functionality without the extra overhead of jQuery, while providing the same awesome data-binding features you expect from Vue. Vue-select has no dependencies other than Vue.
|
||||
Rather than bringing in jQuery just to use Select2 or Chosen, this Vue.js component provides similar functionality without the extra overhead of jQuery, while providing the same awesome data-binding features you expect from Vue. Vue-select has no JavaScript dependencies other than Vue.
|
||||
|
||||
Currently the `vue-select` component includes bootstrap classes in the markup, that provide some default layout styles. If you're not using bootstrap in your project, you'll need to add some CSS yourself. This will likely be updated in the future so that the bootstrap classes are optional, and if they're not included, some sensible default layout-related CSS will be used.
|
||||
|
||||
## Demo
|
||||
[http://sagalbot.github.io/vue-select/](http://sagalbot.github.io/vue-select/)
|
||||
@@ -35,12 +37,15 @@ export default {
|
||||
- `value` Represents the currently selected value(s). Can be `null`, an empty string, or `[]`. If `multiple` is true, the current value will be represented in an array, otherwise it will be a single string or object, depending on what you've passed for `options`.
|
||||
- twoway: true,
|
||||
- required: true
|
||||
- `options` An array of strings or objects to be used as dropdown choices. Supports `['foo','bar']` & `[{label: 'Foo', value: 'foo'}]`. When using the `[{}]` syntax, the objects in the array can have as many properties as you need, as long as the object contains `value` and `label` keys.
|
||||
- `options` An array of strings or objects to be used as dropdown choices. Supports `['foo','bar']` & `[{label: 'Foo', value: 'foo'}]`. When using the `[{}]` syntax, the objects in the array can have as many properties as you need, as long as the object contains a `label` key. If you are working with options where you are unable to add this key, you can also set a custom key using the `label` prop.
|
||||
- type: `Array`
|
||||
- default: `[]`
|
||||
- `label` This is the key that will be used when generating labels for options. ex) If your dataset is `[{name: 'John Doe', age: 35}]` and you want the name to be used as the label, you would set the label prop as `name`.
|
||||
- type: `String`
|
||||
- default: `'label'`
|
||||
- `maxHeight` Limit the height of the dropdown menu.
|
||||
- type: String
|
||||
- default: '400px'
|
||||
- default: `'400px'`
|
||||
- `searchable` Toggle filtering of options.
|
||||
- type: Boolean
|
||||
- default: true
|
||||
@@ -49,23 +54,22 @@ export default {
|
||||
- default: true
|
||||
- `placeholder` Equivalent to `placeholder` attribute on an `<input>`.
|
||||
- type: String
|
||||
- default: ' '
|
||||
- `transition` Vue `transition` prop applied to the `.dropdown-menu`.
|
||||
- type: Boolean
|
||||
- default: true
|
||||
- default: ''
|
||||
- `transition` Vue `transition` prop applied to the `.dropdown-menu`. The component itself does not include any CSS for transitions, they must be implemented yourself.
|
||||
- type: String
|
||||
- default: ''
|
||||
|
||||
## Todos:
|
||||
- load data from an ajax source with vue-resource
|
||||
- rich option formatting with slots/partials
|
||||
- fix layout/toggle issues when `searchable` is false
|
||||
- `simple` prop that disables `search` and keeps a static `placeholder` regardless of current selection (useful for things like icon button dropdowns)
|
||||
- less opinionated styles / only include css necessary to acheive layout (no colors, etc)
|
||||
- ~~ability to pre-select options when using `[{label: 'Foo', value: 'foo'}]` syntax (already works with `['foo','bar','baz']` syntax)~~
|
||||
- ~~fix layout issues with multiple selections~~
|
||||
- ~~tags overflow outside `.dropdown`~~
|
||||
- ~~search input overflows outside `.dropdown`~~
|
||||
- ~~use an actual element instead of `:after` to detect clicks on dropdown caret~~
|
||||
- fix layout/toggle issues when `searchable` is false
|
||||
- `simple` prop that disables `search` and keeps a static `placeholder` regardless of current selection (useful for things like icon button dropdowns)
|
||||
- less opinionated styles / only include css necessary to acheive layout (no colors, etc)
|
||||
- ability to pre-select options when using `[{label: 'Foo', value: 'foo'}]` syntax (already works with `['foo','bar','baz']` syntax)
|
||||
- (maybe) load data from an ajax source with vue-resource
|
||||
- more tests!!
|
||||
|
||||
|
||||
## Build Setup for Contributing
|
||||
|
||||
@@ -78,14 +82,11 @@ npm install
|
||||
# serve with hot reload at localhost:8080
|
||||
npm run dev
|
||||
|
||||
# build for demo site (without minification so visitors can inspect with Vue Dev Tools)
|
||||
npm run build
|
||||
|
||||
# lint all *.js and *.vue files
|
||||
npm run lint
|
||||
|
||||
# run unit tests
|
||||
npm test
|
||||
|
||||
# watch files and run unit tests on save
|
||||
npm run test-watch
|
||||
```
|
||||
|
||||
For more information see the [docs for vueify](https://github.com/vuejs/vueify).
|
||||
|
||||
+2
-1
@@ -10,7 +10,8 @@
|
||||
"uglify": "cross-env NODE_ENV=production browserify -e src/main.js | uglifyjs -c warnings=false -m > dist/build.js",
|
||||
"build": "cross-env NODE_ENV=production browserify -e src/main.js > dist/build.js",
|
||||
"lint": "eslint --ext .js,.vue src test/unit",
|
||||
"test": "karma start karma.conf.js"
|
||||
"test": "karma start karma.conf.js",
|
||||
"test-watch": "karma start karma.conf.js --single-run false --auto-watch true"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
|
||||
@@ -183,6 +183,10 @@
|
||||
clearSearchOnSelect: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: 'label'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -235,6 +239,11 @@
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the visibility of the dropdown menu.
|
||||
* @param {Event} e
|
||||
* @return {void}
|
||||
*/
|
||||
toggleDropdown( e ) {
|
||||
if( e.target === this.$els.openIndicator || e.target === this.$els.search || e.target === this.$els.toggle || e.target === this.$el ) {
|
||||
if( this.open ) {
|
||||
@@ -262,22 +271,46 @@
|
||||
return option;
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate the option label text. If {option}
|
||||
* is an object, return option[this.label].
|
||||
*
|
||||
* @param {Object || String} option
|
||||
* @return {String}
|
||||
*/
|
||||
getOptionLabel( option ) {
|
||||
if( typeof option === 'object' && option.label ) {
|
||||
return option.label;
|
||||
if( typeof option === 'object' ) {
|
||||
if( this.label && option[this.label] ) {
|
||||
return option[this.label];
|
||||
} else if( option.label ) {
|
||||
return option.label
|
||||
}
|
||||
}
|
||||
|
||||
return option;
|
||||
},
|
||||
|
||||
/**
|
||||
* Move the typeAheadPointer visually up the list by
|
||||
* subtracting the current index by one.
|
||||
* @return {void}
|
||||
*/
|
||||
typeAheadUp() {
|
||||
if (this.typeAheadPointer > 0) this.typeAheadPointer--
|
||||
},
|
||||
|
||||
/**
|
||||
* Move the typeAheadPointer visually down the list by
|
||||
* adding the current index by one.
|
||||
* @return {void}
|
||||
*/
|
||||
typeAheadDown() {
|
||||
if (this.typeAheadPointer < this.filteredOptions.length - 1) this.typeAheadPointer++
|
||||
},
|
||||
|
||||
/**
|
||||
* Select the option at the current typeAheadPointer position.
|
||||
* @return {void}
|
||||
*/
|
||||
typeAheadSelect() {
|
||||
if( this.filteredOptions[ this.typeAheadPointer ] ) {
|
||||
this.select( this.filteredOptions[ this.typeAheadPointer ] );
|
||||
|
||||
+33
-35
@@ -5,79 +5,58 @@ import vSelect from '../../src/components/Select.vue'
|
||||
|
||||
describe('Select.vue', () => {
|
||||
|
||||
// it('sets open to true when search on focus and false on blur', () => {
|
||||
// const vm = new Vue({
|
||||
// template: '<div><v-select :value.sync="value"></v-select></div>',
|
||||
// components: { vSelect },
|
||||
// data: {
|
||||
// value: ['one'],
|
||||
// options: ['one','two','three']
|
||||
// }
|
||||
// }).$mount()
|
||||
//
|
||||
// vm.$children[0].$els.search.focus()
|
||||
// expect(vm.$children[0].$get('open')).toEqual(true)
|
||||
// })
|
||||
|
||||
it('can accept an array with pre-selected values', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :value.sync="value"></v-select></div>',
|
||||
template: '<div><v-select :options="options" :value.sync="value"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: ['one'],
|
||||
options: ['one','two','three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
expect(vm.$children[0].value).toEqual(['one'])
|
||||
})
|
||||
|
||||
it('can accept an array of objects and pre-selected value (single)', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :value.sync="value"></v-select></div>',
|
||||
template: '<div><v-select :options="options" :value.sync="value"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: {label: 'This is Foo', value: 'foo'},
|
||||
options: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}]
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
expect( vm.$children[0].$get('value').value ).toEqual( 'foo' )
|
||||
expect( vm.$children[0].$get('value').label ).toEqual( 'This is Foo' )
|
||||
})
|
||||
|
||||
it('can accept an array of objects and pre-selected values (multiple)', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :value.sync="value" :multiple="true"></v-select></div>',
|
||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}],
|
||||
options: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}]
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
var values = vm.$children[0].$get('value')
|
||||
var labels = []
|
||||
|
||||
labels = values.map( value => value.label )
|
||||
values = values.map( value => value.value )
|
||||
|
||||
expect( values ).toEqual( ['foo', 'bar'] )
|
||||
expect( labels ).toEqual( ['This is Foo', 'This is Bar'] )
|
||||
})
|
||||
|
||||
it('removes the given tag when its close icon is clicked', (done) => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :value.sync="value" :multiple="true"></v-select></div>',
|
||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: ['one'],
|
||||
options: ['one','two','three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
vm.$children[0].$els.toggle.querySelector('.close').click()
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$children[0].$get('value')).toEqual([])
|
||||
done()
|
||||
@@ -87,14 +66,13 @@ describe('Select.vue', () => {
|
||||
it('removes the last item in the value array on delete keypress when multiple is true', () => {
|
||||
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :value.sync="value" :multiple="true"></v-select></div>',
|
||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: ['one','two'],
|
||||
options: ['one','two','three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
vm.$children[0].maybeDeleteValue()
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$children[0].$get('value')).toEqual(['one'])
|
||||
@@ -103,14 +81,13 @@ describe('Select.vue', () => {
|
||||
|
||||
it('sets the value to null on delete keypress when multiple is false', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :value.sync="value"></v-select></div>',
|
||||
template: '<div><v-select :options="options" :value.sync="value"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: 'one',
|
||||
options: ['one','two','three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
vm.$children[0].maybeDeleteValue()
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$children[0].$get('value')).toEqual(null)
|
||||
@@ -119,7 +96,7 @@ describe('Select.vue', () => {
|
||||
|
||||
it('can determine if the value prop is empty', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :value.sync="value"></v-select></div>',
|
||||
template: '<div><v-select :options="options" :value.sync="value"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: [],
|
||||
@@ -142,16 +119,14 @@ describe('Select.vue', () => {
|
||||
|
||||
it('resets the selected values when the options property changes', (done) => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :value.sync="value" :multiple="true"></v-select></div>',
|
||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: ['one'],
|
||||
options: ['one','two','three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
vm.$children[0].options = ['four','five','six']
|
||||
|
||||
Vue.nextTick(() => {
|
||||
expect(vm.$children[0].$get('value')).toEqual([])
|
||||
done()
|
||||
@@ -160,17 +135,40 @@ describe('Select.vue', () => {
|
||||
|
||||
it('can retain values present in a new array of options', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :value.sync="value"></v-select></div>',
|
||||
template: '<div><v-select :options="options" :value.sync="value"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: ['one'],
|
||||
options: ['one','two','three']
|
||||
}
|
||||
}).$mount()
|
||||
|
||||
vm.$children[0].$set('options', ['one','five','six'])
|
||||
expect(vm.$children[0].value).toEqual(['one'])
|
||||
})
|
||||
|
||||
it('can generate labels using the default label key', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: [{label: 'Baz'}],
|
||||
options: [{label: 'Foo'}, {label: 'Baz'}]
|
||||
}
|
||||
}).$mount()
|
||||
expect(vm.$children[0].$els.toggle.querySelector('.selected-tag').textContent).toContain('Baz')
|
||||
})
|
||||
|
||||
it('can generate labels using a custom label key', () => {
|
||||
const vm = new Vue({
|
||||
template: '<div><v-select label="name" :options="options" :value.sync="value" :multiple="true"></v-select></div>',
|
||||
components: { vSelect },
|
||||
data: {
|
||||
value: [{name: 'Baz'}],
|
||||
options: [{name: 'Foo'}, {name: 'Baz'}]
|
||||
}
|
||||
}).$mount()
|
||||
expect(vm.$children[0].$els.toggle.querySelector('.selected-tag').textContent).toContain('Baz')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user