2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-25 11:10:32 +03:00

fix #54 and add regression test, use 2 space indents

This commit is contained in:
Jeff Sagal
2016-06-16 15:00:08 -07:00
parent 6789c2abd5
commit 0a15c00b0c
3 changed files with 588 additions and 554 deletions
+4 -3
View File
@@ -7,7 +7,8 @@ Rather than bringing in jQuery just to use Select2 or Chosen, this Vue.js compon
#### Features #### Features
- **Tagging Support (+v.1.1.0)** - **AJAX Support +v1.2.0**
- Tagging Support **+v.1.1.0**
- No JS Dependencies - No JS Dependencies
- List Filtering/Searching - List Filtering/Searching
- Supports Vuex - Supports Vuex
@@ -17,9 +18,9 @@ Rather than bringing in jQuery just to use Select2 or Chosen, this Vue.js compon
#### Upcoming/In Progress #### Upcoming/In Progress
- ~~Tagging (adding options not present in list, see `taggable` branch)~~ **added in v.1.1.0** - ~~Tagging (adding options not present in list, see `taggable` branch)~~ **+v.1.1.0**
- ~~Asyncronous Option Loading~~ **+v.1.2.0**
- Rich Option Templating - Rich Option Templating
- Asyncronous Option Loading
## Live Examples & Docs ## Live Examples & Docs
[http://sagalbot.github.io/vue-select/](http://sagalbot.github.io/vue-select/) [http://sagalbot.github.io/vue-select/](http://sagalbot.github.io/vue-select/)
+40 -32
View File
@@ -21,7 +21,7 @@
} }
.v-select .open-indicator:before { .v-select .open-indicator:before {
border-color: rgba(60,60,60,.5); border-color: rgba(60, 60, 60, .5);
border-style: solid; border-style: solid;
border-width: 0.25em 0.25em 0 0; border-width: 0.25em 0.25em 0 0;
content: ''; content: '';
@@ -46,7 +46,7 @@
display: block; display: block;
padding: 0; padding: 0;
background: none; background: none;
border: 1px solid rgba(60,60,60,.26); border: 1px solid rgba(60, 60, 60, .26);
border-radius: 4px; border-radius: 4px;
white-space: normal; white-space: normal;
} }
@@ -113,7 +113,7 @@
} }
.v-select .active a { .v-select .active a {
background: rgba(50,50,50,.1); background: rgba(50, 50, 50, .1);
color: #333; color: #333;
} }
@@ -130,23 +130,26 @@
right: 10px; right: 10px;
font-size: 5px; font-size: 5px;
text-indent: -9999em; text-indent: -9999em;
border-top: .9em solid rgba(100,100,100,.1); border-top: .9em solid rgba(100, 100, 100, .1);
border-right: .9em solid rgba(100,100,100,.1); border-right: .9em solid rgba(100, 100, 100, .1);
border-bottom: .9em solid rgba(100,100,100,.1); border-bottom: .9em solid rgba(100, 100, 100, .1);
border-left: .9em solid rgba(60,60,60,.45); border-left: .9em solid rgba(60, 60, 60, .45);
transform: translateZ(0); transform: translateZ(0);
animation: vSelectSpinner 1.1s infinite linear; animation: vSelectSpinner 1.1s infinite linear;
transition: opacity .1s; transition: opacity .1s;
} }
.v-select.loading .spinner { .v-select.loading .spinner {
opacity: 1; opacity: 1;
} }
.v-select .spinner, .v-select .spinner,
.v-select .spinner:after { .v-select .spinner:after {
border-radius: 50%; border-radius: 50%;
width: 5em; width: 5em;
height: 5em; height: 5em;
} }
@-webkit-keyframes vSelectSpinner { @-webkit-keyframes vSelectSpinner {
0% { 0% {
transform: rotate(0deg); transform: rotate(0deg);
@@ -155,6 +158,7 @@
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
@keyframes vSelectSpinner { @keyframes vSelectSpinner {
0% { 0% {
transform: rotate(0deg); transform: rotate(0deg);
@@ -172,7 +176,7 @@
{{ placeholder }} {{ placeholder }}
</span> </span>
<span class="selected-tag" v-for="option in valueAsArray"> <span class="selected-tag" v-for="option in valueAsArray" track-by="$index">
{{ getOptionLabel(option) }} {{ getOptionLabel(option) }}
<button v-if="multiple" @click="select(option)" type="button" class="close"> <button v-if="multiple" @click="select(option)" type="button" class="close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
@@ -249,7 +253,9 @@
*/ */
options: { options: {
type: Array, type: Array,
default() { return [] }, default() {
return []
},
}, },
/** /**
@@ -327,8 +333,8 @@
getOptionLabel: { getOptionLabel: {
type: Function, type: Function,
default(option) { default(option) {
if( typeof option === 'object' ) { if (typeof option === 'object') {
if( this.label && option[this.label] ) { if (this.label && option[this.label]) {
return option[this.label] return option[this.label]
} }
} }
@@ -388,14 +394,18 @@
watch: { watch: {
value(val, old) { value(val, old) {
if (this.multiple) {
this.onChange ? this.onChange(val) : null
} else {
this.onChange && val !== old ? this.onChange(val) : null this.onChange && val !== old ? this.onChange(val) : null
}
}, },
options() { options() {
if (!this.taggable) { if (!this.taggable) {
this.$set('value', this.multiple ? [] : null) this.$set('value', this.multiple ? [] : null)
} }
}, },
multiple( val ) { multiple(val) {
this.$set('value', val ? [] : null) this.$set('value', val ? [] : null)
} }
}, },
@@ -412,19 +422,17 @@
if (this.taggable && !this.optionExists(option)) { if (this.taggable && !this.optionExists(option)) {
option = this.createOption(option) option = this.createOption(option)
if( this.pushTags ) { if (this.pushTags) {
this.options.push(option) this.options.push(option)
} }
} }
if (this.multiple) { if (this.multiple) {
if (!this.value) { if (!this.value) {
this.$set('value', [option]) this.$set('value', [option])
} else { } else {
this.value.push(option) this.value.push(option)
} }
} else { } else {
this.value = option this.value = option
} }
@@ -448,7 +456,7 @@
this.$els.search.blur() this.$els.search.blur()
} }
if( this.clearSearchOnSelect ) { if (this.clearSearchOnSelect) {
this.search = '' this.search = ''
} }
}, },
@@ -459,8 +467,8 @@
* @return {void} * @return {void}
*/ */
toggleDropdown(e) { toggleDropdown(e) {
if( e.target === this.$els.openIndicator || e.target === this.$els.search || e.target === this.$els.toggle || e.target === this.$el ) { if (e.target === this.$els.openIndicator || e.target === this.$els.search || e.target === this.$els.toggle || e.target === this.$el) {
if( this.open ) { if (this.open) {
this.$els.search.blur() // dropdown will close on blur this.$els.search.blur() // dropdown will close on blur
} else { } else {
this.open = true this.open = true
@@ -474,13 +482,13 @@
* @param {Object||String} option * @param {Object||String} option
* @return {Boolean} True when selected || False otherwise * @return {Boolean} True when selected || False otherwise
*/ */
isOptionSelected( option ) { isOptionSelected(option) {
if( this.multiple && this.value ) { if (this.multiple && this.value) {
let selected = false let selected = false
this.value.forEach(opt => { this.value.forEach(opt => {
if( typeof opt === 'object' && opt[this.label] === option ) { if (typeof opt === 'object' && opt[this.label] === option) {
selected = true selected = true
} else if( opt === option ) { } else if (opt === option) {
selected = true selected = true
} }
}) })
@@ -496,7 +504,7 @@
* @return {[type]} [description] * @return {[type]} [description]
*/ */
onEscape() { onEscape() {
if( ! this.search.length ) { if (!this.search.length) {
this.$els.search.blur() this.$els.search.blur()
} else { } else {
this.search = '' this.search = ''
@@ -509,7 +517,7 @@
* @return {this.value} * @return {this.value}
*/ */
maybeDeleteValue() { maybeDeleteValue() {
if( ! this.$els.search.value.length && this.value ) { if (!this.$els.search.value.length && this.value) {
return this.multiple ? this.value.pop() : this.$set('value', null) return this.multiple ? this.value.pop() : this.$set('value', null)
} }
}, },
@@ -525,9 +533,9 @@
let exists = false let exists = false
this.options.forEach(opt => { this.options.forEach(opt => {
if( typeof opt === 'object' && opt[this.label] === option ) { if (typeof opt === 'object' && opt[this.label] === option) {
exists = true exists = true
} else if( opt === option ) { } else if (opt === option) {
exists = true exists = true
} }
}) })
@@ -556,7 +564,7 @@
* @return {String} Placeholder text * @return {String} Placeholder text
*/ */
searchPlaceholder() { searchPlaceholder() {
if( this.isValueEmpty && this.placeholder ) { if (this.isValueEmpty && this.placeholder) {
return this.placeholder; return this.placeholder;
} }
}, },
@@ -582,11 +590,11 @@
* @return {Boolean} * @return {Boolean}
*/ */
isValueEmpty() { isValueEmpty() {
if( this.value ) { if (this.value) {
if( typeof this.value === 'object' ) { if (typeof this.value === 'object') {
return ! Object.keys(this.value).length return !Object.keys(this.value).length
} }
return ! this.value.length return !this.value.length
} }
return true; return true;
@@ -597,7 +605,7 @@
* @return {Array} * @return {Array}
*/ */
valueAsArray() { valueAsArray() {
if( this.multiple ) { if (this.multiple) {
return this.value return this.value
} else if (this.value) { } else if (this.value) {
return [this.value] return [this.value]
+38 -13
View File
@@ -190,32 +190,57 @@ describe('Select.vue', () => {
expect(vm.$children[0].isOptionSelected('one')).toEqual(true) expect(vm.$children[0].isOptionSelected('one')).toEqual(true)
}) })
describe('onChange Callback', () => {
it('can run a callback when the selection changes', (done) => { it('can run a callback when the selection changes', (done) => {
const vm = new Vue({ const vm = new Vue({
template: '<div><v-select :on-change="foo" value="bar" :options="options"></v-select></div>', template: `<div><v-select :value="['foo']" :options="['foo','bar','baz']" :on-change="cb"></v-select></div>`,
components: {vSelect}, components: {vSelect},
data: {
val: null,
options: ['foo', 'bar', 'baz']
},
methods: { methods: {
foo(value) { cb(val) {
this.val = value
} }
} }
}).$mount() }).$mount()
vm.$children[0].select('foo') spyOn(vm.$children[0], 'onChange')
Vue.nextTick(function () {
expect(vm.$get('val')).toEqual('foo')
vm.$children[0].$set('value', 'baz') vm.$children[0].select('bar')
Vue.nextTick(function () {
expect(vm.$get('val')).toEqual('baz') Vue.nextTick(() => {
expect(vm.$children[0].onChange).toHaveBeenCalledWith('bar')
vm.$children[0].select('baz')
Vue.nextTick(() => {
expect(vm.$children[0].onChange).toHaveBeenCalledWith('baz')
done() done()
}) })
}) })
}) })
it('should run onChange when multiple is true and the value changes', (done) => {
const vm = new Vue({
template: `<div><v-select v-ref:select :value="['foo']" :options="['foo','bar','baz']" multiple :on-change="cb"></v-select></div>`,
methods: {
cb(val) {
}
}
}).$mount()
spyOn(vm.$children[0], 'onChange')
vm.$children[0].select('bar')
Vue.nextTick(() => {
expect(vm.$children[0].onChange).toHaveBeenCalledWith(['foo','bar'])
vm.$children[0].select('baz')
Vue.nextTick(() => {
expect(vm.$children[0].onChange).toHaveBeenCalledWith(['foo','bar','baz'])
done()
})
})
})
})
}) })
describe('Toggling Dropdown', () => { describe('Toggling Dropdown', () => {