mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-19 09:50:33 +03:00
fixes:
- change currentSelection to mutableValue - change currentOptions to mutableOptions - change showLoading to mutableLoading - add default onChange function that emits an input event - allows the use of v-model syntax on the component - since spies on props throw warnings because they are now immutable, refactor tests so spies aren't required todo: - update docs - 1 failing test from inject-loader issue
This commit is contained in:
+2
-1
@@ -3,4 +3,5 @@ node_modules
|
|||||||
npm-debug.log
|
npm-debug.log
|
||||||
.idea
|
.idea
|
||||||
test/unit/coverage
|
test/unit/coverage
|
||||||
.coveralls.yml
|
.coveralls.yml
|
||||||
|
.flowconfig
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ module.exports = {
|
|||||||
'src': path.resolve(__dirname, '../src'),
|
'src': path.resolve(__dirname, '../src'),
|
||||||
'assets': path.resolve(__dirname, '../docs/assets'),
|
'assets': path.resolve(__dirname, '../docs/assets'),
|
||||||
'mixins': path.resolve(__dirname, '../src/mixins'),
|
'mixins': path.resolve(__dirname, '../src/mixins'),
|
||||||
'components': path.resolve(__dirname, '../docs/components'),
|
'components': path.resolve(__dirname, '../src/components'),
|
||||||
'vue$': 'vue/dist/vue.js'
|
'vue$': 'vue/dist/vue.common.js',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolveLoader: {
|
resolveLoader: {
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-select",
|
"name": "vue-select",
|
||||||
"version": "1.3.3",
|
"version": "2.0.0-alpha",
|
||||||
"description": "A native Vue.js component that provides similar functionality to Select2 without the overhead of jQuery.",
|
"description": "A native Vue.js component that provides similar functionality to Select2 without the overhead of jQuery.",
|
||||||
"author": "Jeff Sagal <sagalbot@gmail.com>",
|
"author": "Jeff Sagal <sagalbot@gmail.com>",
|
||||||
"private": false,
|
"private": false,
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
"vue": "^2.0.3",
|
"vue": "^2.0.3",
|
||||||
"vue-hot-reload-api": "^1.2.0",
|
"vue-hot-reload-api": "^1.2.0",
|
||||||
"vue-html-loader": "^1.2.3",
|
"vue-html-loader": "^1.2.3",
|
||||||
"vue-loader": "^9.6.0",
|
"vue-loader": "^9.9.5",
|
||||||
"vue-resource": "^1.0.3",
|
"vue-resource": "^1.0.3",
|
||||||
"vue-style-loader": "^1.0.0",
|
"vue-style-loader": "^1.0.0",
|
||||||
"vuex": "^0.6.3",
|
"vuex": "^0.6.3",
|
||||||
|
|||||||
+96
-57
@@ -202,7 +202,7 @@
|
|||||||
<i ref="openIndicator" role="presentation" class="open-indicator"></i>
|
<i ref="openIndicator" role="presentation" class="open-indicator"></i>
|
||||||
|
|
||||||
<slot name="spinner">
|
<slot name="spinner">
|
||||||
<div class="spinner" v-show="showLoading">Loading...</div>
|
<div class="spinner" v-show="mutableLoading">Loading...</div>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -237,7 +237,7 @@
|
|||||||
/**
|
/**
|
||||||
* Contains the currently selected value. Very similar to a
|
* Contains the currently selected value. Very similar to a
|
||||||
* `value` attribute on an <input>. You can listen for changes
|
* `value` attribute on an <input>. You can listen for changes
|
||||||
* using 'change' event using v-on
|
* using 'change' event using v-on
|
||||||
* @type {Object||String||null}
|
* @type {Object||String||null}
|
||||||
*/
|
*/
|
||||||
value: {
|
value: {
|
||||||
@@ -349,8 +349,12 @@
|
|||||||
* @type {Function}
|
* @type {Function}
|
||||||
* @default {null}
|
* @default {null}
|
||||||
*/
|
*/
|
||||||
onChange: Function,
|
onChange: {
|
||||||
|
type: Function,
|
||||||
|
default: function(val) {
|
||||||
|
this.$emit('input', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable/disable creating options from searchInput.
|
* Enable/disable creating options from searchInput.
|
||||||
@@ -378,7 +382,7 @@
|
|||||||
createOption: {
|
createOption: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: function (newOption) {
|
default: function (newOption) {
|
||||||
if (typeof this.currentOptions[0] === 'object') {
|
if (typeof this.mutableOptions[0] === 'object') {
|
||||||
return {[this.label]: newOption}
|
return {[this.label]: newOption}
|
||||||
}
|
}
|
||||||
return newOption
|
return newOption
|
||||||
@@ -399,45 +403,80 @@
|
|||||||
return {
|
return {
|
||||||
search: '',
|
search: '',
|
||||||
open: false,
|
open: false,
|
||||||
currentSelection: null,
|
mutableValue: null,
|
||||||
currentOptions: [],
|
mutableOptions: [],
|
||||||
showLoading: false
|
mutableLoading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
value(val, old) {
|
/**
|
||||||
this.currentSelection = val
|
* When the value prop changes, update
|
||||||
|
* the internal mutableValue.
|
||||||
|
* @param {mixed} val
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
value(val) {
|
||||||
|
this.mutableValue = val
|
||||||
},
|
},
|
||||||
currentSelection(val, old) {
|
|
||||||
|
/**
|
||||||
|
* Maybe run the onChange callback.
|
||||||
|
* @param {string|object} val
|
||||||
|
* @param {string|object} old
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
mutableValue(val, old) {
|
||||||
if (this.multiple) {
|
if (this.multiple) {
|
||||||
this.onChange ? this.onChange(val) : null
|
this.onChange ? this.onChange(val) : null
|
||||||
this.$emit('change', val)
|
|
||||||
} else {
|
} else {
|
||||||
if(val !== old) {
|
this.onChange && val !== old ? this.onChange(val) : null
|
||||||
this.onChange? this.onChange(val) : null
|
|
||||||
this.$emit('change', val)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When options change, update
|
||||||
|
* the internal mutableOptions.
|
||||||
|
* @param {array} val
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
options(val) {
|
options(val) {
|
||||||
this.currentOptions = val
|
this.mutableOptions = val
|
||||||
},
|
},
|
||||||
currentOptions() {
|
|
||||||
|
/**
|
||||||
|
* Maybe reset the mutableValue
|
||||||
|
* when mutableOptions change.
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
mutableOptions() {
|
||||||
if (!this.taggable && this.resetOnOptionsChange) {
|
if (!this.taggable && this.resetOnOptionsChange) {
|
||||||
this.currentSelection = this.multiple ? [] : null
|
this.mutableValue = this.multiple ? [] : null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
multiple(val) {
|
|
||||||
this.currentSelection = val ? [] : null
|
/**
|
||||||
|
* Always reset the mutableValue when
|
||||||
|
* the multiple prop changes.
|
||||||
|
* @param {Boolean} val
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
multiple(val) {
|
||||||
|
this.mutableValue = val ? [] : null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
created() {
|
||||||
|
this.mutableValue = this.value
|
||||||
|
this.mutableOptions = this.options.slice(0)
|
||||||
|
this.mutableLoading = this.loading
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select a given option.
|
* Select a given option.
|
||||||
* @param {Object||String} option
|
* @param {Object|String} option
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
select(option) {
|
select(option) {
|
||||||
@@ -448,19 +487,18 @@
|
|||||||
option = this.createOption(option)
|
option = this.createOption(option)
|
||||||
|
|
||||||
if (this.pushTags) {
|
if (this.pushTags) {
|
||||||
console.log("adding " + option +" to "+ this.currentOptions)
|
this.mutableOptions.push(option)
|
||||||
this.currentOptions.push(option)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.multiple) {
|
if (this.multiple) {
|
||||||
if (!this.currentSelection) {
|
if (!this.mutableValue) {
|
||||||
this.currentSelection = [option]
|
this.mutableValue = [option]
|
||||||
} else {
|
} else {
|
||||||
this.currentSelection.push(option)
|
this.mutableValue.push(option)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.currentSelection = option
|
this.mutableValue = option
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,27 +507,27 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* De-select a given option.
|
* De-select a given option.
|
||||||
* @param {Object||String} option
|
* @param {Object|String} option
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
deselect(option) {
|
deselect(option) {
|
||||||
if (this.multiple) {
|
if (this.multiple) {
|
||||||
let ref = -1
|
let ref = -1
|
||||||
this.currentSelection.forEach((val) => {
|
this.mutableValue.forEach((val) => {
|
||||||
if (val === option || typeof val === 'object' && val[this.label] === option[this.label]) {
|
if (val === option || typeof val === 'object' && val[this.label] === option[this.label]) {
|
||||||
ref = val
|
ref = val
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
var index = this.currentSelection.indexOf(ref)
|
var index = this.mutableValue.indexOf(ref)
|
||||||
this.currentSelection.splice(index, 1)
|
this.mutableValue.splice(index, 1)
|
||||||
} else {
|
} else {
|
||||||
this.currentSelection = null
|
this.mutableValue = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called from this.select after each selection.
|
* Called from this.select after each selection.
|
||||||
* @param {Object||String} option
|
* @param {Object|String} option
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
onAfterSelect(option) {
|
onAfterSelect(option) {
|
||||||
@@ -521,13 +559,13 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given option is currently selected.
|
* Check if the given option is currently selected.
|
||||||
* @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.currentSelection) {
|
if (this.multiple && this.mutableValue) {
|
||||||
let selected = false
|
let selected = false
|
||||||
this.currentSelection.forEach(opt => {
|
this.mutableValue.forEach(opt => {
|
||||||
if (typeof opt === 'object' && opt[this.label] === option[this.label]) {
|
if (typeof opt === 'object' && opt[this.label] === option[this.label]) {
|
||||||
selected = true
|
selected = true
|
||||||
} else if (opt === option) {
|
} else if (opt === option) {
|
||||||
@@ -537,7 +575,7 @@
|
|||||||
return selected
|
return selected
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.currentSelection === option
|
return this.mutableValue === option
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -559,14 +597,14 @@
|
|||||||
* @return {this.value}
|
* @return {this.value}
|
||||||
*/
|
*/
|
||||||
maybeDeleteValue() {
|
maybeDeleteValue() {
|
||||||
if (!this.$refs.search.value.length && this.currentSelection) {
|
if (!this.$refs.search.value.length && this.mutableValue) {
|
||||||
return this.multiple ? this.currentSelection.pop() : this.currentSelection = null
|
return this.multiple ? this.mutableValue.pop() : this.mutableValue = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if an option exists
|
* Determine if an option exists
|
||||||
* within this.currentOptions array.
|
* within this.mutableOptions array.
|
||||||
*
|
*
|
||||||
* @param {Object || String} option
|
* @param {Object || String} option
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
@@ -574,7 +612,7 @@
|
|||||||
optionExists(option) {
|
optionExists(option) {
|
||||||
let exists = false
|
let exists = false
|
||||||
|
|
||||||
this.currentOptions.forEach(opt => {
|
this.mutableOptions.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) {
|
||||||
@@ -596,7 +634,7 @@
|
|||||||
return {
|
return {
|
||||||
open: this.open,
|
open: this.open,
|
||||||
searchable: this.searchable,
|
searchable: this.searchable,
|
||||||
loading: this.showLoading
|
loading: this.mutableLoading
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -620,7 +658,13 @@
|
|||||||
* @return {array}
|
* @return {array}
|
||||||
*/
|
*/
|
||||||
filteredOptions() {
|
filteredOptions() {
|
||||||
let options = this.$options.filters.filterBy?this.$options.filters.filterBy(this.currentOptions, this.search):this.currentOptions
|
|
||||||
|
let options = this.mutableOptions.filter((option) => {
|
||||||
|
if( typeof option === 'object' ) {
|
||||||
|
return option[this.label].indexOf(this.search) > -1
|
||||||
|
}
|
||||||
|
return option.indexOf(this.search) > -1
|
||||||
|
})
|
||||||
if (this.taggable && this.search.length && !this.optionExists(this.search)) {
|
if (this.taggable && this.search.length && !this.optionExists(this.search)) {
|
||||||
options.unshift(this.search)
|
options.unshift(this.search)
|
||||||
}
|
}
|
||||||
@@ -632,11 +676,11 @@
|
|||||||
* @return {Boolean}
|
* @return {Boolean}
|
||||||
*/
|
*/
|
||||||
isValueEmpty() {
|
isValueEmpty() {
|
||||||
if (this.currentSelection) {
|
if (this.mutableValue) {
|
||||||
if (typeof this.currentSelection === 'object') {
|
if (typeof this.mutableValue === 'object') {
|
||||||
return !Object.keys(this.currentSelection).length
|
return !Object.keys(this.mutableValue).length
|
||||||
}
|
}
|
||||||
return !this.currentSelection.length
|
return !this.mutableValue.length
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -648,19 +692,14 @@
|
|||||||
*/
|
*/
|
||||||
valueAsArray() {
|
valueAsArray() {
|
||||||
if (this.multiple) {
|
if (this.multiple) {
|
||||||
return this.currentSelection
|
return this.mutableValue
|
||||||
} else if (this.currentSelection) {
|
} else if (this.mutableValue) {
|
||||||
return [this.currentSelection]
|
return [this.mutableValue]
|
||||||
}
|
}
|
||||||
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created: function() {
|
|
||||||
this.currentSelection = this.value
|
|
||||||
this.currentOptions = this.options.slice(0)
|
|
||||||
this.showLoading = this.loading
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
+8
-2
@@ -1,5 +1,6 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import vSelect from '../src/components/Select.vue'
|
import vSelect from './components/Select.vue'
|
||||||
|
import countries from '../old_docs/data/advanced.js'
|
||||||
|
|
||||||
Vue.component('v-select', vSelect)
|
Vue.component('v-select', vSelect)
|
||||||
|
|
||||||
@@ -7,5 +8,10 @@ Vue.config.devtools = true
|
|||||||
|
|
||||||
/* eslint-disable no-new */
|
/* eslint-disable no-new */
|
||||||
new Vue({
|
new Vue({
|
||||||
el: 'body'
|
el: '#app',
|
||||||
|
data: {
|
||||||
|
placeholder: "placeholder",
|
||||||
|
value: null,
|
||||||
|
options: countries
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+1
-1
@@ -64,4 +64,4 @@ module.exports = {
|
|||||||
return this.showLoading = toggle
|
return this.showLoading = toggle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,11 +64,11 @@ describe('Select.vue', () => {
|
|||||||
template: '<div><v-select :options="options" :value="value"></v-select></div>',
|
template: '<div><v-select :options="options" :value="value"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: ['one'],
|
value: 'one',
|
||||||
options: ['one', 'two', 'three']
|
options: ['one', 'two', 'three']
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
expect(vm.$children[0].currentSelection).toEqual(vm.value)
|
expect(vm.$children[0].mutableValue).toEqual(vm.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can accept an array of objects and pre-selected value (single)', () => {
|
it('can accept an array of objects and pre-selected value (single)', () => {
|
||||||
@@ -80,7 +80,7 @@ describe('Select.vue', () => {
|
|||||||
options: [{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()
|
}).$mount()
|
||||||
expect(vm.$children[0].currentSelection).toEqual(vm.value)
|
expect(vm.$children[0].mutableValue).toEqual(vm.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can accept an array of objects and pre-selected values (multiple)', () => {
|
it('can accept an array of objects and pre-selected values (multiple)', () => {
|
||||||
@@ -92,7 +92,7 @@ describe('Select.vue', () => {
|
|||||||
options: [{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()
|
}).$mount()
|
||||||
expect(vm.$children[0].currentSelection).toEqual(vm.value)
|
expect(vm.$children[0].mutableValue).toEqual(vm.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can deselect a pre-selected object', () => {
|
it('can deselect a pre-selected object', () => {
|
||||||
@@ -104,7 +104,7 @@ describe('Select.vue', () => {
|
|||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].select({label: 'This is Foo', value: 'foo'})
|
vm.$children[0].select({label: 'This is Foo', value: 'foo'})
|
||||||
expect(vm.$children[0].currentSelection.length).toEqual(1)
|
expect(vm.$children[0].mutableValue.length).toEqual(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can deselect a pre-selected string', () => {
|
it('can deselect a pre-selected string', () => {
|
||||||
@@ -116,7 +116,7 @@ describe('Select.vue', () => {
|
|||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].select('foo')
|
vm.$children[0].select('foo')
|
||||||
expect(vm.$children[0].currentSelection.length).toEqual(1)
|
expect(vm.$children[0].mutableValue.length).toEqual(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can determine if the value prop is empty', () => {
|
it('can determine if the value prop is empty', () => {
|
||||||
@@ -164,10 +164,10 @@ describe('Select.vue', () => {
|
|||||||
vm.multiple = false
|
vm.multiple = false
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual(null)
|
expect(vm.$children[0].mutableValue).toEqual(null)
|
||||||
vm.multiple = true
|
vm.multiple = true
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual([])
|
expect(vm.$children[0].mutableValue).toEqual([])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -175,20 +175,20 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
it('can retain values present in a new array of options', () => {
|
it('can retain values present in a new array of options', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value"></v-select></div>',
|
template: '<div><v-select :options="options" v-model="value"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: ['one'],
|
value: ['one'],
|
||||||
options: ['one', 'two', 'three']
|
options: ['one', 'two', 'three']
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].options = ['one', 'five', 'six']
|
vm.options = ['one', 'five', 'six']
|
||||||
expect(vm.$children[0].currentSelection).toEqual(['one'])
|
expect(vm.$children[0].mutableValue).toEqual(['one'])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can determine if an object is already selected', () => {
|
it('can determine if an object is already selected', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" multiple :value.sync="value"></v-select></div>',
|
template: '<div><v-select :options="options" multiple v-model="value"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: [{label: 'one'}],
|
value: [{label: 'one'}],
|
||||||
@@ -199,54 +199,57 @@ describe('Select.vue', () => {
|
|||||||
expect(vm.$children[0].isOptionSelected({label: 'one'})).toEqual(true)
|
expect(vm.$children[0].isOptionSelected({label: 'one'})).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('can use v-model syntax for a two way binding to a parent component', (done) => {
|
||||||
|
const vm = new Vue({
|
||||||
|
template: '<div><v-select :options="options" v-model="value"></v-select></div>',
|
||||||
|
components: {vSelect},
|
||||||
|
data: {
|
||||||
|
value: 'foo',
|
||||||
|
options: ['foo','bar','baz']
|
||||||
|
}
|
||||||
|
}).$mount()
|
||||||
|
|
||||||
|
expect(vm.$children[0].value).toEqual('foo')
|
||||||
|
expect(vm.$children[0].mutableValue).toEqual('foo')
|
||||||
|
|
||||||
|
vm.$children[0].mutableValue = 'bar'
|
||||||
|
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
expect(vm.value).toEqual('bar')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('change Event', () => {
|
describe('change Event', () => {
|
||||||
it('can run a callback when the selection changes', (done) => {
|
it('will trigger the input event when the selection changes', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: `<div><v-select :value="['foo']" :options="['foo','bar','baz']" v-on:change="cb"></v-select></div>`,
|
template: `<div><v-select ref="select" :value="['foo']" :options="['foo','bar','baz']" v-on:input="foo = arguments[0]"></v-select></div>`,
|
||||||
components: {vSelect},
|
data: {
|
||||||
methods: {
|
foo: ''
|
||||||
cb(val) {
|
|
||||||
console.log("Value Changed to "+val)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
spyOn(vm, 'cb')
|
vm.$refs.select.select('bar')
|
||||||
|
|
||||||
vm.$children[0].select('bar')
|
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.cb).toHaveBeenCalledWith('bar')
|
expect(vm.foo).toEqual('bar')
|
||||||
vm.$children[0].select('baz')
|
done()
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
|
||||||
expect(vm.cb).toHaveBeenCalledWith('baz')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should run change when multiple is true and the value changes', (done) => {
|
it('should run change when multiple is true and the value changes', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: `<div><v-select ref="select" :value="['foo']" :options="['foo','bar','baz']" multiple v-on:change="cb"></v-select></div>`,
|
template: `<div><v-select ref="select" :value="['foo']" :options="['foo','bar','baz']" multiple v-on:input="foo = arguments[0]"></v-select></div>`,
|
||||||
methods: {
|
data: {
|
||||||
cb(val) {
|
foo: ''
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
spyOn(vm, 'cb')
|
vm.$refs.select.select('bar')
|
||||||
|
|
||||||
vm.$children[0].select('bar')
|
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.cb).toHaveBeenCalledWith(['foo','bar'])
|
expect(vm.foo).toEqual(['foo','bar'])
|
||||||
vm.$children[0].select('baz')
|
done()
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
|
||||||
expect(vm.cb).toHaveBeenCalledWith(['foo','bar','baz'])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -487,12 +490,14 @@ describe('Select.vue', () => {
|
|||||||
return {top: 0, bottom: 1}
|
return {top: 0, bottom: 1}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let mock = Mock({
|
||||||
|
'../mixins/pointerScroll': {methods}
|
||||||
|
})
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="[\'one\', \'two\', \'three\']"></v-select></div>',
|
template: `<div><v-select :options="['one', 'two', 'three']"></v-select></div>`,
|
||||||
components: {
|
components: {
|
||||||
'v-select': Mock({
|
'v-select': mock
|
||||||
'../mixins/pointerScroll': {methods}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
@@ -525,7 +530,7 @@ describe('Select.vue', () => {
|
|||||||
describe('Removing values', () => {
|
describe('Removing values', () => {
|
||||||
it('can remove the given tag when its close icon is clicked', (done) => {
|
it('can remove the given tag when its close icon is clicked', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true"></v-select></div>',
|
template: '<div><v-select :options="options" v-model="value" :multiple="true"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: ['one'],
|
value: ['one'],
|
||||||
@@ -534,7 +539,7 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].$refs.toggle.querySelector('.close').click()
|
vm.$children[0].$refs.toggle.querySelector('.close').click()
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual([])
|
expect(vm.$children[0].mutableValue).toEqual([])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -542,7 +547,7 @@ describe('Select.vue', () => {
|
|||||||
it('should remove the last item in the value array on delete keypress when multiple is true', () => {
|
it('should remove the last item in the value array on delete keypress when multiple is true', () => {
|
||||||
|
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true"></v-select></div>',
|
template: '<div><v-select :options="options" v-model="value" :multiple="true"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: ['one', 'two'],
|
value: ['one', 'two'],
|
||||||
@@ -551,13 +556,13 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].maybeDeleteValue()
|
vm.$children[0].maybeDeleteValue()
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual(['one'])
|
expect(vm.$children[0].mutableValue).toEqual(['one'])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should set value to null on delete keypress when multiple is false', () => {
|
it('should set value to null on delete keypress when multiple is false', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value"></v-select></div>',
|
template: '<div><v-select :options="options" v-model="value"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: 'one',
|
value: 'one',
|
||||||
@@ -566,7 +571,7 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].maybeDeleteValue()
|
vm.$children[0].maybeDeleteValue()
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual(null)
|
expect(vm.$children[0].mutableValue).toEqual(null)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -574,7 +579,7 @@ describe('Select.vue', () => {
|
|||||||
describe('Labels', () => {
|
describe('Labels', () => {
|
||||||
it('can generate labels using a custom label key', () => {
|
it('can generate labels using a custom label key', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select label="name" :options="options" :value.sync="value" :multiple="true"></v-select></div>',
|
template: '<div><v-select label="name" :options="options" v-model="value" :multiple="true"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: [{name: 'Baz'}],
|
value: [{name: 'Baz'}],
|
||||||
@@ -594,13 +599,11 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
expect(vm.$children[0].searchPlaceholder).toEqual('foo')
|
expect(vm.$children[0].searchPlaceholder).toEqual('foo')
|
||||||
vm.$children[0].currentSelection = {label: 'one'}
|
vm.$children[0].mutableValue = {label: 'one'}
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].searchPlaceholder).not.toBeDefined()
|
expect(vm.$children[0].searchPlaceholder).not.toBeDefined()
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
// expect(vm.$children[0].searchPlaceholder()).toEqual('foo')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -670,7 +673,7 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
searchSubmit(vm, 'three')
|
searchSubmit(vm, 'three')
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual(['one', 'three'])
|
expect(vm.$children[0].mutableValue).toEqual(['one', 'three'])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -687,7 +690,7 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
searchSubmit(vm, 'two')
|
searchSubmit(vm, 'two')
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual([{label: 'one'}, {label: 'two'}])
|
expect(vm.$children[0].mutableValue).toEqual([{label: 'one'}, {label: 'two'}])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -703,7 +706,7 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
searchSubmit(vm, 'three')
|
searchSubmit(vm, 'three')
|
||||||
expect(vm.$children[0].currentOptions).toEqual(['one', 'two', 'three'])
|
expect(vm.$children[0].mutableOptions).toEqual(['one', 'two', 'three'])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('wont add a freshly created option/tag to the options list when pushTags is false', () => {
|
it('wont add a freshly created option/tag to the options list when pushTags is false', () => {
|
||||||
@@ -717,7 +720,7 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
searchSubmit(vm, 'three')
|
searchSubmit(vm, 'three')
|
||||||
expect(vm.$children[0].currentOptions).toEqual(['one', 'two'])
|
expect(vm.$children[0].mutableOptions).toEqual(['one', 'two'])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should select an existing option if the search string matches a string from options', (done) => {
|
it('should select an existing option if the search string matches a string from options', (done) => {
|
||||||
@@ -735,7 +738,7 @@ describe('Select.vue', () => {
|
|||||||
searchSubmit(vm)
|
searchSubmit(vm)
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection[0]).toBe(two)
|
expect(vm.$children[0].mutableValue[0]).toBe(two)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -757,7 +760,7 @@ describe('Select.vue', () => {
|
|||||||
// This needs to be wrapped in nextTick() twice so that filteredOptions can
|
// This needs to be wrapped in nextTick() twice so that filteredOptions can
|
||||||
// calculate after setting the search text, and move the typeAheadPointer index to 0.
|
// calculate after setting the search text, and move the typeAheadPointer index to 0.
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection.label).toBe(two.label)
|
expect(vm.$children[0].mutableValue.label).toBe(two.label)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -771,9 +774,9 @@ describe('Select.vue', () => {
|
|||||||
options: [{label: 'one'}]
|
options: [{label: 'one'}]
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].options = [{label: 'two'}]
|
vm.$children[0].mutableOptions = [{label: 'two'}]
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual([{label: 'one'}])
|
expect(vm.$children[0].mutableValue).toEqual([{label: 'one'}])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -795,17 +798,20 @@ describe('Select.vue', () => {
|
|||||||
it('should trigger the onSearch callback when the search text changes', (done) => {
|
it('should trigger the onSearch callback when the search text changes', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select ref="select" :on-search="foo"></v-select></div>',
|
template: '<div><v-select ref="select" :on-search="foo"></v-select></div>',
|
||||||
|
data: {
|
||||||
|
called: false
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
foo() {
|
foo(val) {
|
||||||
|
this.called = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
spyOn(vm.$refs.select, 'onSearch')
|
|
||||||
vm.$refs.select.search = 'foo'
|
vm.$refs.select.search = 'foo'
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$refs.select.onSearch).toHaveBeenCalledWith('foo', vm.$refs.select.toggleLoading)
|
expect(vm.called).toEqual('foo')
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -813,18 +819,22 @@ describe('Select.vue', () => {
|
|||||||
it('should not trigger the onSearch callback if the search text is empty', (done) => {
|
it('should not trigger the onSearch callback if the search text is empty', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select ref="select" search="foo" :on-search="foo"></v-select></div>',
|
template: '<div><v-select ref="select" search="foo" :on-search="foo"></v-select></div>',
|
||||||
|
data: { called: false },
|
||||||
methods: {
|
methods: {
|
||||||
foo() {
|
foo(val) {
|
||||||
|
this.called = ! this.called
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
spyOn(vm.$refs.select, 'onSearch')
|
vm.$refs.select.search = 'foo'
|
||||||
vm.$refs.select.search = ''
|
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$refs.select.onSearch).not.toHaveBeenCalled()
|
expect(vm.called).toBe(true)
|
||||||
done()
|
vm.$refs.select.search = ''
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
expect(vm.called).toBe(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -874,9 +884,9 @@ describe('Select.vue', () => {
|
|||||||
options: ['one', 'two', 'three']
|
options: ['one', 'two', 'three']
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].options = ['four', 'five', 'six']
|
vm.$children[0].mutableOptions = ['four', 'five', 'six']
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual('one')
|
expect(vm.$children[0].mutableValue).toEqual('one')
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -890,9 +900,9 @@ describe('Select.vue', () => {
|
|||||||
options: ['one', 'two', 'three']
|
options: ['one', 'two', 'three']
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].options = ['four', 'five', 'six']
|
vm.$children[0].mutableOptions = ['four', 'five', 'six']
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].currentSelection).toEqual(null)
|
expect(vm.$children[0].mutableValue).toEqual(null)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user