2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-05-17 02:29:37 +03:00

Merge branch 'master' into gitbook

# Conflicts:
#	docs/md/OnChange.md
This commit is contained in:
Jeff
2018-01-13 11:43:00 -08:00
9 changed files with 428 additions and 56 deletions
+18 -8
View File
@@ -9,17 +9,15 @@
<!--<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">-->
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"> -->
<style>
html,
body,
#app {
height: 100vh;
}
#app {
height: 95vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
justify-content: flex-start;
flex-wrap: wrap;
align-content: center;
}
.v-select {
@@ -32,13 +30,25 @@
<body>
<div id="app">
<v-select placeholder="default" :options="options"></v-select>
<v-select placeholder="default, RTL" :options="options" dir="rtl"></v-select>
<v-select placeholder="multiple" multiple :options="options"></v-select>
<v-select placeholder="multiple, taggable" multiple taggable :options="options" no-drop></v-select>
<v-select placeholder="multiple, taggable, push-tags" multiple push-tags taggable :options="[{label: 'Foo', value: 'foo'}]"></v-select>
<v-select placeholder="multiple, closeOnSelect=true" multiple :options="['cat', 'dog', 'bear']"></v-select>
<v-select placeholder="multiple, closeOnSelect=false" multiple :close-on-select="false" :options="['cat', 'dog', 'bear']"></v-select>
<v-select placeholder="unsearchable" :options="options" :searchable="false"></v-select>
<v-select placeholder="searchable=false" :options="options" :searchable="false"></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>
<template slot="selected-option" slot-scope="option">
{{option.label}}
</template>
<template slot="option" slot-scope="option">
{{option.label}} ({{option.value}})
</template>
</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="filterable=false, @search=searchPeople" label="first_name" :filterable="false" @search="searchPeople" :options="people"></v-select>
</div>
</body>
+2 -2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -122,7 +122,7 @@
</div>
<div class="col-md-6">
<pre><v-code lang="markup">&#x3C;v-select v-on:change=&#x22;consoleCallback&#x22; :options=&#x22;countries&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code></pre>
<pre><v-code lang="markup">&#x3C;v-select :on-change=&#x22;consoleCallback&#x22; :options=&#x22;countries&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code></pre>
<pre><v-code lang="javascript">methods: {
consoleCallback(val) {
console.dir(JSON.stringify(val))
+26
View File
@@ -0,0 +1,26 @@
### Change Event <small>Vuex Compatibility</small>
vue-select provides a `change` event. This function is passed the currently selected value(s) as it's only parameter.
This is very useful when integrating with Vuex, as it will allow your to trigger an action to update your vuex state object. Choose a callback and see it in action.
<div class="form-inline">
<div class="radio"><label><input type="radio" v-model="callback" value="console"> `console.log(val)`</label> </div>
<div class="radio"><label><input type="radio" v-model="callback" value="alert"> `alert(val)`</label> </div>
</div>
```html
<v-select :on-change="consoleCallback" :options="countries"></v-select>
```
```js
methods: {
consoleCallback(val) {
console.dir(JSON.stringify(val))
},
alertCallback(val) {
alert(JSON.stringify(val))
}
}
```
+2 -7
View File
@@ -1,12 +1,13 @@
{
"name": "vue-select",
"version": "2.2.0",
"version": "2.4.0",
"description": "A native Vue.js component that provides similar functionality to Select2 without the overhead of jQuery.",
"author": "Jeff Sagal <sagalbot@gmail.com>",
"private": false,
"main": "dist/vue-select.js",
"license": "MIT",
"scripts": {
"start": "npm run dev",
"dev": "node build/dev-server.js",
"docs": "gitbook serve docs",
"build": "node build/build.js",
@@ -14,12 +15,6 @@
"test": "karma start test/unit/karma.conf.js --single-run",
"test-watch": "karma start test/unit/karma.conf.js --single-run=false --auto-watch=true"
},
"browserify": {
"transform": [
"vueify",
"babelify"
]
},
"repository": {
"type": "git",
"url": "https://github.com/sagalbot/vue-select.git"
+180 -31
View File
@@ -3,12 +3,30 @@
position: relative;
font-family: sans-serif;
}
.v-select,
.v-select * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* Rtl support */
.v-select.rtl .open-indicator {
left: 10px;
right: auto;
}
.v-select.rtl .selected-tag {
float: right;
margin-right: 3px;
margin-left: 1px;
}
.v-select.rtl .dropdown-menu {
text-align: right;
}
.v-select.rtl .dropdown-toggle .clear {
left: 30px;
right: auto;
}
/* Open Indicator */
.v-select .open-indicator {
position: absolute;
@@ -20,7 +38,6 @@
transition: all 150ms cubic-bezier(1.000, -0.115, 0.975, 0.855);
transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855);
opacity: 1;
transition: opacity .1s;
height: 20px; width: 10px;
}
.v-select .open-indicator:before {
@@ -58,7 +75,6 @@
border: 1px solid rgba(60, 60, 60, .26);
border-radius: 4px;
white-space: normal;
transition: border-radius .25s;
}
.v-select .dropdown-toggle:after {
visibility: hidden;
@@ -68,6 +84,22 @@
clear: both;
height: 0;
}
/* Clear Button */
.v-select .dropdown-toggle .clear {
position: absolute;
bottom: 9px;
right: 30px;
font-size: 23px;
font-weight: 700;
line-height: 1;
color: rgba(60, 60, 60, .5);
padding: 0;
border: 0;
background-color: transparent;
cursor: pointer;
}
/* Dropdown Toggle States */
.v-select.searchable .dropdown-toggle {
cursor: text;
@@ -174,14 +206,14 @@
background: none;
position: relative;
box-shadow: none;
float: left;
clear: none;
}
/* Search Input States */
.v-select.unsearchable input[type="search"] {
max-width: 1px;
opacity: 0;
}
/* List Items */
.v-select.unsearchable input[type="search"]:hover {
cursor: pointer;
}
/* List Items */
.v-select li {
line-height: 1.42857143; /* Normalize line height */
}
@@ -233,6 +265,17 @@
width: 5em;
height: 5em;
}
/* Disabled state */
.v-select.disabled .dropdown-toggle,
.v-select.disabled .dropdown-toggle .clear,
.v-select.disabled .dropdown-toggle input,
.v-select.disabled .selected-tag .close,
.v-select.disabled .open-indicator {
cursor: not-allowed;
background-color: rgb(248, 248, 248);
}
/* Loading Spinner States */
.v-select.loading .spinner {
opacity: 1;
@@ -266,15 +309,20 @@
</style>
<template>
<div class="dropdown v-select" :class="dropdownClasses">
<div ref="toggle" @mousedown.prevent="toggleDropdown" class="dropdown-toggle">
<div :dir="dir" class="dropdown v-select" :class="dropdownClasses">
<div ref="toggle" @mousedown.prevent="toggleDropdown" :class="['dropdown-toggle', 'clearfix']">
<span class="selected-tag" v-for="option in valueAsArray" v-bind:key="option.index">
{{ getOptionLabel(option) }}
<button v-if="multiple" @click="deselect(option)" type="button" class="close" aria-label="Remove option">
<span aria-hidden="true">&times;</span>
</button>
</span>
<slot v-for="option in valueAsArray" name="selected-option-container"
:option="option" :deselect="deselect">
<span class="selected-tag" v-bind:key="option.index">
<slot name="selected-option" v-bind="option">
{{ getOptionLabel(option) }}
</slot>
<button v-if="multiple" :disabled="disabled" @click="deselect(option)" type="button" class="close" aria-label="Remove option">
<span aria-hidden="true">&times;</span>
</button>
</span>
</slot>
<input
ref="search"
@@ -283,18 +331,32 @@
@keyup.esc="onEscape"
@keydown.up.prevent="typeAheadUp"
@keydown.down.prevent="typeAheadDown"
@keyup.enter.prevent="typeAheadSelect"
@keydown.enter.prevent="typeAheadSelect"
@blur="onSearchBlur"
@focus="onSearchFocus"
type="search"
class="form-control"
autocomplete="false"
:disabled="disabled"
:placeholder="searchPlaceholder"
:tabindex="tabindex"
:readonly="!searchable"
:style="{ width: isValueEmpty ? '100%' : 'auto' }"
:id="inputId"
aria-label="Search for option"
>
<button
v-show="showClearButton"
:disabled="disabled"
@click="clearSelection"
type="button"
class="clear"
title="Clear selection"
>
<span aria-hidden="true">&times;</span>
</button>
<i v-if="!noDrop" ref="openIndicator" role="presentation" class="open-indicator"></i>
<slot name="spinner">
@@ -306,7 +368,9 @@
<ul ref="dropdownMenu" v-if="dropdownOpen" class="dropdown-menu" :style="{ 'max-height': maxHeight }">
<li v-for="(option, index) in filteredOptions" v-bind:key="index" :class="{ active: isOptionSelected(option), highlight: index === typeAheadPointer }" @mouseover="typeAheadPointer = index">
<a @mousedown.prevent="select(option)">
<slot name="option" v-bind="option">
{{ getOptionLabel(option) }}
</slot>
</a>
</li>
<li v-if="!filteredOptions.length" class="no-options">
@@ -341,7 +405,7 @@
* If you are using an array of objects, vue-select will look for
* a `label` key (ex. [{label: 'This is Foo', value: 'foo'}]). A
* custom label key can be set with the `label` prop.
* @type {Object}
* @type {Array}
*/
options: {
type: Array,
@@ -350,6 +414,15 @@
},
},
/**
* Disable the entire component.
* @type {Boolean}
*/
disabled: {
type: Boolean,
default: false
},
/**
* Sets the max-height property on the dropdown list.
* @deprecated
@@ -371,7 +444,7 @@
/**
* Equivalent to the `multiple` attribute on a `<select>` input.
* @type {Object}
* @type {Boolean}
*/
multiple: {
type: Boolean,
@@ -380,7 +453,7 @@
/**
* Equivalent to the `placeholder` attribute on an `<input>`.
* @type {Object}
* @type {String}
*/
placeholder: {
type: String,
@@ -429,6 +502,7 @@
/**
* Callback to generate the label text. If {option}
* is an object, returns option[this.label] by default.
* @type {Function}
* @param {Object || String} option
* @return {String}
*/
@@ -436,6 +510,13 @@
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 ${JSON.stringify(option)}.\n` +
'http://sagalbot.github.io/vue-select/#ex-labels'
)
}
if (this.label && option[this.label]) {
return option[this.label]
}
@@ -444,12 +525,27 @@
}
},
/**
* 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
* value(s) change. When integrating with Vuex, use this callback to trigger
* an action, rather than using :value.sync to retreive the selected value.
* @type {Function}
* @default {null}
* @param {Object || String} val
*/
onChange: {
type: Function,
@@ -467,6 +563,15 @@
default: false
},
/**
* Set the tabindex for the input field.
* @type {Number}
*/
tabindex: {
type: Number,
default: null
},
/**
* When true, newly created tags will be added to
* the options list.
@@ -477,6 +582,17 @@
default: false
},
/**
* When true, existing options will be filtered
* by the search text. Should not be used in conjunction
* with taggable.
* @type {Boolean}
*/
filterable: {
type: Boolean,
default: true
},
/**
* User defined function for adding Options
* @type {Function}
@@ -517,7 +633,18 @@
*/
inputId: {
type: String
}
},
/**
* Sets RTL support. Accepts 'ltr', 'rtl', 'auto'.
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir
* @type {String}
* @default 'auto'
*/
dir: {
type: String,
default: 'auto'
},
},
data() {
@@ -645,6 +772,14 @@
}
},
/**
* Clears the currently selected value(s)
* @return {void}
*/
clearSelection() {
this.mutableValue = this.multiple ? [] : null
},
/**
* Called from this.select after each selection.
* @param {Object|String} option
@@ -671,8 +806,10 @@
if (this.open) {
this.$refs.search.blur() // dropdown will close on blur
} else {
this.open = true
this.$refs.search.focus()
if (!this.disabled) {
this.open = true
this.$refs.search.focus()
}
}
}
},
@@ -796,7 +933,9 @@
searching: this.searching,
searchable: this.searchable,
unsearchable: !this.searchable,
loading: this.mutableLoading
loading: this.mutableLoading,
rtl: this.dir === 'rtl',
disabled: this.disabled
}
},
@@ -806,7 +945,7 @@
*/
clearSearchOnBlur() {
return this.clearSearchOnSelect && !this.multiple
},
},
/**
* Return the current state of the
@@ -846,13 +985,15 @@
* @return {array}
*/
filteredOptions() {
if (!this.filterable && !this.taggable) {
return this.mutableOptions.slice()
}
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 this.filterFunction(option, label, this.search)
})
if (this.taggable && this.search.length && !this.optionExists(this.search)) {
options.unshift(this.search)
@@ -883,10 +1024,18 @@
if (this.multiple) {
return this.mutableValue
} else if (this.mutableValue) {
return [this.mutableValue]
return [].concat(this.mutableValue)
}
return []
},
/**
* Determines if the clear button should be displayed.
* @return {Boolean}
*/
showClearButton() {
return !this.multiple && !this.open && this.mutableValue != null
}
},
+12 -1
View File
@@ -17,13 +17,24 @@ new Vue({
placeholder: "placeholder",
value: null,
options: countries,
ajaxRes: []
ajaxRes: [],
people: []
},
methods: {
search(search, loading) {
loading(true)
this.getRepositories(search, loading, this)
},
searchPeople(search, loading) {
loading(true)
this.getPeople(loading, this)
},
getPeople: debounce((loading, vm) => {
vm.$http.get(`https://reqres.in/api/users?per_page=10`).then(res => {
vm.people = res.data.data
loading(false)
})
}, 250),
getRepositories: debounce((search, loading, vm) => {
vm.$http.get(`https://api.github.com/search/repositories?q=${search}`).then(res => {
vm.ajaxRes = res.data.items
+186 -5
View File
@@ -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')
@@ -65,7 +65,7 @@ function searchSubmit(vm, search = false) {
vm.$children[0].search = search
}
trigger(vm.$children[0].$refs.search, 'keyup', function (e) {
trigger(vm.$children[0].$refs.search, 'keydown', function (e) {
e.keyCode = 13
})
}
@@ -295,6 +295,15 @@ describe('Select.vue', () => {
expect(vm.$refs.select.filteredOptions).toEqual(['bar','baz'])
})
it('should not filter the array of strings if filterable is false', () => {
const vm = new Vue({
template: `<div><v-select ref="select" :filterable="false" :options="['foo','bar','baz']" v-model="value"></v-select></div>`,
data: {value: 'foo'}
}).$mount()
vm.$refs.select.search = 'ba'
expect(vm.$refs.select.filteredOptions).toEqual(['foo','bar','baz'])
})
it('should filter without case-sensitivity', () => {
const vm = new Vue({
template: `<div><v-select ref="select" :options="['Foo','Bar','Baz']" v-model="value"></v-select></div>`,
@@ -312,9 +321,40 @@ 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: `<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'},
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', () => {
it('should not open the dropdown when the el is clicked but the component is disabled', (done) => {
const vm = new Vue({
template: '<div><v-select :options="options" :value="value" disabled></v-select></div>',
components: {vSelect},
data: {
value: [{label: 'one'}],
options: [{label: 'one'}]
}
}).$mount()
vm.$children[0].toggleDropdown({target: vm.$children[0].$refs.search})
Vue.nextTick(() => {
Vue.nextTick(() => {
expect(vm.$children[0].open).toEqual(false)
done()
})
})
})
it('should open the dropdown when the el is clicked', (done) => {
const vm = new Vue({
template: '<div><v-select :options="options" :value="value"></v-select></div>',
@@ -674,6 +714,22 @@ describe('Select.vue', () => {
})
})
it('should not remove tag when close icon is clicked and component is disabled', (done) => {
const vm = new Vue({
template: '<div><v-select disabled multiple :options="options" v-model="value"></v-select></div>',
components: {vSelect},
data: {
value: ['one'],
options: ['one', 'two', 'three']
}
}).$mount()
vm.$children[0].$refs.toggle.querySelector('.close').click()
Vue.nextTick(() => {
expect(vm.$children[0].mutableValue).toEqual(['one'])
done()
})
})
it('should remove the last item in the value array on delete keypress when multiple is true', () => {
const vm = new Vue({
@@ -726,7 +782,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()
@@ -853,6 +909,21 @@ describe('Select.vue', () => {
expect(vm.$children[0].mutableOptions).toEqual(['one', 'two', 'three'])
})
it('should add a freshly created option/tag to the options list when pushTags is true and filterable is false', () => {
const vm = new Vue({
template: '<div><v-select :options="options" push-tags :value="value" :filterable="false" :multiple="true" :taggable="true"></v-select></div>',
components: {vSelect},
data: {
value: ['one'],
options: ['one', 'two']
}
}).$mount()
searchSubmit(vm, 'three')
expect(vm.$children[0].mutableOptions).toEqual(['one', 'two', 'three'])
expect(vm.$children[0].filteredOptions).toEqual(['one', 'two', 'three'])
})
it('wont add a freshly created option/tag to the options list when pushTags is false', () => {
const vm = new Vue({
template: '<div><v-select :options="options" :value="value" :multiple="true" :taggable="true"></v-select></div>',
@@ -867,6 +938,21 @@ describe('Select.vue', () => {
expect(vm.$children[0].mutableOptions).toEqual(['one', 'two'])
})
it('wont add a freshly created option/tag to the options list when pushTags is false and filterable is false', () => {
const vm = new Vue({
template: '<div><v-select :options="options" :value="value" :multiple="true" :filterable="false" :taggable="true"></v-select></div>',
components: {vSelect},
data: {
value: ['one'],
options: ['one', 'two']
}
}).$mount()
searchSubmit(vm, 'three')
expect(vm.$children[0].mutableOptions).toEqual(['one', 'two'])
expect(vm.$children[0].filteredOptions).toEqual(['one', 'two'])
})
it('should select an existing option if the search string matches a string from options', (done) => {
let two = 'two'
const vm = new Vue({
@@ -908,6 +994,28 @@ describe('Select.vue', () => {
})
})
it('should select an existing option if the search string matches an objects label from options when filter-options is false', (done) => {
let two = {label: 'two'}
const vm = new Vue({
template: '<div><v-select :options="options" taggable :filterable="false"></v-select></div>',
data: {
options: [{label: 'one'}, two]
}
}).$mount()
vm.$children[0].search = 'two'
Vue.nextTick(() => {
searchSubmit(vm)
// 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.
Vue.nextTick(() => {
expect(vm.$children[0].mutableValue.label).toBe(two.label)
done()
})
})
})
it('should not reset the selected value when the options property changes', (done) => {
const vm = new Vue({
template: '<div><v-select :options="options" :value="value" :multiple="true" taggable></v-select></div>',
@@ -924,6 +1032,22 @@ describe('Select.vue', () => {
})
})
it('should not reset the selected value when the options property changes when filterable is false', (done) => {
const vm = new Vue({
template: '<div><v-select :options="options" :value="value" :multiple="true" :filterable="false" taggable></v-select></div>',
components: {vSelect},
data: {
value: [{label: 'one'}],
options: [{label: 'one'}]
}
}).$mount()
vm.$children[0].mutableOptions = [{label: 'two'}]
Vue.nextTick(() => {
expect(vm.$children[0].mutableValue).toEqual([{label: 'one'}])
done()
})
})
it('should not allow duplicate tags when using string options', (done) => {
const vm = new Vue({
template: `<div><v-select ref="select" taggable multiple></v-select></div>`,
@@ -1154,11 +1278,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('')
@@ -1187,4 +1311,61 @@ describe('Select.vue', () => {
})
})
})
describe( 'Clear button', () => {
it( 'should be displayed on single select when value is selected', () => {
const VueSelect = Vue.extend( vSelect )
const vm = new VueSelect({
propsData: {
options: ['foo','bar'],
value: 'foo'
}
}).$mount()
expect(vm.showClearButton).toEqual(true)
})
it( 'should not be displayed on multiple select', () => {
const VueSelect = Vue.extend( vSelect )
const vm = new VueSelect({
propsData: {
options: ['foo','bar'],
value: 'foo',
multiple: true
}
}).$mount()
expect(vm.showClearButton).toEqual(false)
})
it( 'should remove selected value when clicked', () => {
const VueSelect = Vue.extend( vSelect )
const vm = new VueSelect({
propsData: {
options: ['foo','bar'],
value: 'foo'
}
}).$mount()
expect(vm.mutableValue).toEqual('foo')
vm.$el.querySelector( 'button.clear' ).click()
expect(vm.mutableValue).toEqual(null)
})
it( 'should be disabled when component is disabled', () => {
const VueSelect = Vue.extend( vSelect )
const vm = new VueSelect({
propsData: {
options: ['foo','bar'],
value: 'foo',
disabled: true
}
}).$mount()
const buttonEl = vm.$el.querySelector( 'button.clear' )
expect(buttonEl.disabled).toEqual(true);
})
});
})