mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-19 09:50:33 +03:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -4,3 +4,4 @@ npm-debug.log
|
|||||||
.idea
|
.idea
|
||||||
test/unit/coverage
|
test/unit/coverage
|
||||||
.coveralls.yml
|
.coveralls.yml
|
||||||
|
.flowconfig
|
||||||
|
|||||||
@@ -2,9 +2,5 @@ language: node_js
|
|||||||
node_js:
|
node_js:
|
||||||
- "5"
|
- "5"
|
||||||
- "5.1"
|
- "5.1"
|
||||||
- "4"
|
|
||||||
- "4.2"
|
|
||||||
- "4.1"
|
|
||||||
- "4.0"
|
|
||||||
after_success:
|
after_success:
|
||||||
- codeclimate-test-reporter < ./test/unit/coverage/lcov.info
|
- codeclimate-test-reporter < ./test/unit/coverage/lcov.info
|
||||||
@@ -1,229 +1,103 @@
|
|||||||
# vue-select [](https://travis-ci.org/sagalbot/vue-select) [](https://codeclimate.com/github/sagalbot/vue-select) [](https://gemnasium.com/github.com/sagalbot/vue-select)  
|
# vue-select [](https://travis-ci.org/sagalbot/vue-select) [](https://codeclimate.com/github/sagalbot/vue-select) [](https://gemnasium.com/github.com/sagalbot/vue-select)  
|
||||||
|
|
||||||
> A native Vue.js component that provides similar functionality to Select2 without the overhead of jQuery.
|
> A native Vue.js select component that provides similar functionality to Select2 without the overhead of jQuery.
|
||||||
|
|
||||||
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, and is designed to mimic [Select2](https://github.com/select2/select2).
|
|
||||||
|
|
||||||
|
|
||||||
#### Features
|
#### Features
|
||||||
|
- AJAX Support
|
||||||
- **AJAX Support +v1.2.0**
|
- Tagging
|
||||||
- Tagging Support **+v.1.1.0**
|
|
||||||
- No JS Dependencies
|
|
||||||
- List Filtering/Searching
|
- List Filtering/Searching
|
||||||
- Supports Vuex
|
- Supports Vuex
|
||||||
- Select Single/Multiple Options
|
- Select Single/Multiple Options
|
||||||
- Bootstrap Friendly Markup
|
- Bootstrap Friendly Markup
|
||||||
- +95% Test Coverage
|
- +95% Test Coverage
|
||||||
|
- ~32kb minified
|
||||||
|
|
||||||
#### Upcoming/In Progress
|
## Documentation
|
||||||
|
- **[Demo & Docs](http://sagalbot.github.io/vue-select/)**
|
||||||
|
- **[Example on JSBin](http://jsbin.com/saxaru/8/edit?html,js,output)**
|
||||||
|
|
||||||
- ~~Tagging (adding options not present in list, see `taggable` branch)~~ **+v.1.1.0**
|
## Install
|
||||||
- ~~Asyncronous Option Loading~~ **+v.1.2.0**
|
|
||||||
- Rich Option Templating
|
|
||||||
|
|
||||||
## Live Examples & Docs
|
###### Vue Compatibility
|
||||||
- [Demo & Docs](http://sagalbot.github.io/vue-select/)
|
- `vue ~2.0` use `vue-select ~2.0`
|
||||||
- [Live Example on JSBin](http://jsbin.com/saxaru/5/edit?html,js,output)
|
- `vue ~1.0` use `vue-select ~1.0`
|
||||||
|
|
||||||
## Install / Usage
|
#### NPM
|
||||||
|
Install the package. _You should install `vue-select@1.3.3` for use with vue `~1.0`._
|
||||||
|
|
||||||
#### NPM Based WorkFlows
|
```bash
|
||||||
``` bash
|
|
||||||
$ npm install vue-select
|
$ npm install vue-select
|
||||||
```
|
```
|
||||||
|
|
||||||
```html
|
Register the component
|
||||||
<template>
|
|
||||||
<div id="myApp">
|
|
||||||
<v-select :value.sync="selected" :options="options"></v-select>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
```js
|
||||||
|
import Vue from 'vue'
|
||||||
import vSelect from 'vue-select'
|
import vSelect from 'vue-select'
|
||||||
export default {
|
Vue.component(vSelect)
|
||||||
components: {vSelect},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
selected: null,
|
|
||||||
options: ['foo','bar','baz']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Browser Globals
|
You may now use the component in your markup
|
||||||
|
|
||||||
`v1.3.0+` no longer requires any toolchain to use the component:
|
|
||||||
|
|
||||||
Just include `vue` & `vue-select.js` - I recommend using [npmcdn](https://npmcdn.com/#/).
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!-- use the latest release -->
|
<v-select v-model="selected" :options="['foo','bar']"></v-select>
|
||||||
<script src="https://npmcdn.com/vue-select@latest"></script>
|
|
||||||
<!-- or point to a specific release -->
|
|
||||||
<script src="https://npmcdn.com/vue-select@1.30"></script>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### CDN
|
||||||
|
|
||||||
|
Just include `vue` & `vue-select.js` - I recommend using [unpkg](https://unpkg.com/#/).
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script scr="https://unpkg.com/vue@latest"></script>
|
||||||
|
<!-- use the latest release -->
|
||||||
|
<script src="https://unpkg.com/vue-select@latest"></script>
|
||||||
|
<!-- or point to a specific release -->
|
||||||
|
<script src="https://unpkg.com/vue-select@1.3.3"></script>
|
||||||
|
```
|
||||||
|
|
||||||
Then register the component in your javascript:
|
Then register the component in your javascript:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
Vue.component('v-select', VueSelect.VueSelect);
|
Vue.component('v-select', VueSelect.VueSelect);
|
||||||
```
|
```
|
||||||
|
|
||||||
From there you can use as normal. Here's an [example on JSBin](http://jsbin.com/saxaru/5/edit?html,js,output).
|
You may now use the component in your markup
|
||||||
|
|
||||||
## Parameters
|
```html
|
||||||
```javascript
|
<v-select v-model="selected" :options="['foo','bar']"></v-select>
|
||||||
/**
|
|
||||||
* Contains the currently selected value. Very similar to a
|
|
||||||
* `value` attribute on an <input>. In most cases, you'll want
|
|
||||||
* to set this as a two-way binding, using :value.sync. However,
|
|
||||||
* this will not work with Vuex, in which case you'll need to use
|
|
||||||
* the onChange callback property.
|
|
||||||
* @type {Object||String||null}
|
|
||||||
*/
|
|
||||||
value: {
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An array of strings or objects to be used as dropdown choices.
|
|
||||||
* 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}
|
|
||||||
*/
|
|
||||||
options: {
|
|
||||||
type: Array,
|
|
||||||
default() { return [] },
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the max-height property on the dropdown list.
|
|
||||||
* @deprecated
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
maxHeight: {
|
|
||||||
type: String,
|
|
||||||
default: '400px'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable/disable filtering the options.
|
|
||||||
* @type {Boolean}
|
|
||||||
*/
|
|
||||||
searchable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Equivalent to the `multiple` attribute on a `<select>` input.
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
multiple: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Equivalent to the `placeholder` attribute on an `<input>`.
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
placeholder: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a Vue transition property on the `.dropdown-menu`. vue-select
|
|
||||||
* does not include CSS for transitions, you'll need to add them yourself.
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
transition: {
|
|
||||||
type: String,
|
|
||||||
default: 'expand'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables/disables clearing the search text when an option is selected.
|
|
||||||
* @type {Boolean}
|
|
||||||
*/
|
|
||||||
clearSearchOnSelect: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells vue-select what key to use when generating option
|
|
||||||
* labels when each `option` is an object.
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
label: {
|
|
||||||
type: String,
|
|
||||||
default: 'label'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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}
|
|
||||||
*/
|
|
||||||
onChange: Function,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enable/disable creating options from searchInput.
|
|
||||||
* @type {Boolean}
|
|
||||||
*/
|
|
||||||
taggable: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When true, newly created tags will be added to
|
|
||||||
* the options list.
|
|
||||||
* @type {Boolean}
|
|
||||||
*/
|
|
||||||
pushTags: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* User defined function for adding Options
|
|
||||||
* @type {Function}
|
|
||||||
*/
|
|
||||||
createOption: {
|
|
||||||
type: Function,
|
|
||||||
default: function (newOption) {
|
|
||||||
if (typeof this.options[0] === 'object') {
|
|
||||||
return {[this.label]: newOption}
|
|
||||||
}
|
|
||||||
return newOption
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Here's an [example on JSBin](http://jsbin.com/saxaru/5/edit?html,js,output).
|
||||||
|
|
||||||
## Build Setup for Contributing
|
## Basic Usage
|
||||||
|
|
||||||
If there's a feature you'd like to see or you find a bug, feel free to fork and submit a PR. If your adding functionality, add tests to go with it.
|
#### Syncing a Selected Value
|
||||||
|
|
||||||
``` bash
|
The most common use case for `vue-select` is to have the chosen value synced with a parent component. `vue-select` takes advantage of the `v-model` syntax to sync values with a parent.
|
||||||
# install dependencies
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# serve with hot reload at localhost:8080
|
```html
|
||||||
npm run dev
|
<v-select v-model="selected"></v-select>
|
||||||
|
|
||||||
# run unit tests
|
|
||||||
npm test
|
|
||||||
|
|
||||||
# run unit tests on save
|
|
||||||
npm run test-watch
|
|
||||||
```
|
```
|
||||||
|
```js
|
||||||
|
new Vue({
|
||||||
|
data: {
|
||||||
|
selected: null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Setting Options
|
||||||
|
|
||||||
|
`vue-select` accepts arrays of strings and objects to use as options through the `options` prop.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<v-select :options="['foo','bar']"></v-select>
|
||||||
|
```
|
||||||
|
|
||||||
|
When provided an array of objects, `vue-select` will display a single value of the object. By default, `vue-select` will look for a key named 'label' on the object to use as display text.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<v-select :options="[{label: 'foo', value: 'Foo'}]"></v-select>
|
||||||
|
```
|
||||||
|
|
||||||
|
### For more information, please visit the [vue-select documentation.](https://sagalbot.github.io/vue-select)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ var projectRoot = path.resolve(__dirname, '../')
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: {
|
entry: {
|
||||||
app: './src/dev.js'
|
app: process.argv.indexOf('--docs') > 0 ? './docs/docs.js' : './src/dev.js',
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: config.build.assetsRoot,
|
path: config.build.assetsRoot,
|
||||||
@@ -19,7 +19,9 @@ 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'),
|
||||||
|
'docs': path.resolve(__dirname, '../docs'),
|
||||||
|
'vue$': 'vue/dist/vue.common.js',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resolveLoader: {
|
resolveLoader: {
|
||||||
@@ -29,21 +31,21 @@ module.exports = {
|
|||||||
loaders: [
|
loaders: [
|
||||||
{
|
{
|
||||||
test: /\.vue$/,
|
test: /\.vue$/,
|
||||||
loader: 'vue'
|
loader: 'vue-loader'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.js$/,
|
test: /\.js$/,
|
||||||
loader: 'babel',
|
loader: 'babel-loader',
|
||||||
include: projectRoot,
|
include: projectRoot,
|
||||||
exclude: /node_modules/
|
exclude: /node_modules/
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.json$/,
|
test: /\.json$/,
|
||||||
loader: 'json'
|
loader: 'json-loader'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.html$/,
|
test: /\.html$/,
|
||||||
loader: 'vue-html'
|
loader: 'vue-html-loader'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.(png|jpe?g|gif)(\?.*)?$/,
|
test: /\.(png|jpe?g|gif)(\?.*)?$/,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Object.keys(baseWebpackConfig.entry).forEach(function (name) {
|
|||||||
|
|
||||||
module.exports = merge(baseWebpackConfig, {
|
module.exports = merge(baseWebpackConfig, {
|
||||||
module: {
|
module: {
|
||||||
loaders: utils.styleLoaders()
|
loaders: utils.styleLoaders().concat({ test: /\.md$/, loader: "html!markdown" })
|
||||||
},
|
},
|
||||||
// eval-source-map is faster for development
|
// eval-source-map is faster for development
|
||||||
devtool: '#eval-source-map',
|
devtool: '#eval-source-map',
|
||||||
@@ -27,8 +27,13 @@ module.exports = merge(baseWebpackConfig, {
|
|||||||
// https://github.com/ampedandwired/html-webpack-plugin
|
// https://github.com/ampedandwired/html-webpack-plugin
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
filename: 'index.html',
|
filename: 'index.html',
|
||||||
template: 'index.html',
|
template: process.argv.indexOf('--docs') > 0 ? './docs/docs.html' : 'dev.html',
|
||||||
inject: true
|
inject: true
|
||||||
})
|
})
|
||||||
]
|
],
|
||||||
|
markdownLoader: {
|
||||||
|
highlight: function (code) {
|
||||||
|
return require('highlight.js').highlightAuto(code).value;
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Vue Select Dev</title>
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"> -->
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-select {
|
||||||
|
width: 25em;
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="app">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+30
-8
@@ -6,10 +6,22 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div id="docs" class="container-fluid">
|
||||||
<div class="col-md-10 col-md-offset-1">
|
<div class="col-md-2 col-md-offset-1">
|
||||||
<examples></examples>
|
<ul class="nav nav-pills nav-stacked">
|
||||||
<params></params>
|
<li><a href="#">Install & Usage</a></li>
|
||||||
|
<li><a href="#">Examples</a></li>
|
||||||
|
<li><a href="#">Ajax</a></li>
|
||||||
|
<li><a href="#">Parameters</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-7">
|
||||||
|
<article v-html="install"></article>
|
||||||
|
<article v-html="vModel"></article>
|
||||||
|
<article v-html="single"></article>
|
||||||
|
<article v-html="reactive"></article>
|
||||||
|
<article v-html="labels"></article>
|
||||||
|
<article v-html="ajax"></article>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -22,11 +34,21 @@
|
|||||||
* for the demo site at http://sagalbot.github.io/vue-select/.
|
* for the demo site at http://sagalbot.github.io/vue-select/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Examples from './components/Examples.vue'
|
// import Examples from './components/Examples.vue'
|
||||||
import Params from './components/Params.vue'
|
// import Params from './components/Params.vue'
|
||||||
import Ajax from './components/snippets/Ajax.vue'
|
// import Ajax from './components/snippets/Ajax.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { Params, Examples, Ajax }
|
// components: { Params, Examples, Ajax }
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
install: require('./md/Install.md'),
|
||||||
|
vModel: require('./md/VModel.md'),
|
||||||
|
single: require('./md/SingleMultiple.md'),
|
||||||
|
reactive: require('./md/ReactiveOptions.md'),
|
||||||
|
labels: require('./md/CustomLabels.md'),
|
||||||
|
ajax: require('./md/Ajax.md'),
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -25,8 +25,10 @@ pre[class*="language-"] {
|
|||||||
-moz-hyphens: none;
|
-moz-hyphens: none;
|
||||||
-ms-hyphens: none;
|
-ms-hyphens: none;
|
||||||
hyphens: none;
|
hyphens: none;
|
||||||
background: #f5f7ff;
|
background: $code-white;
|
||||||
color: #5e6687;
|
color: #5e6687;
|
||||||
|
border-radius: 0;
|
||||||
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
$orange: #F16745;
|
$orange: #e96900;
|
||||||
$yellow: #FFC65D;
|
$yellow: #FFC65D;
|
||||||
$green: #7BC8A4;
|
$green: #42b983;
|
||||||
$blue: #4CC3D9;
|
$blue: #4CC3D9;
|
||||||
$purple: #93648D;
|
$purple: #93648D;
|
||||||
$black: #404040;
|
$black: #34495e;
|
||||||
|
$red: #ff6666;
|
||||||
|
|
||||||
// Code
|
// Code
|
||||||
$code-blue: #66d9ef;
|
$code-blue: #66d9ef;
|
||||||
$code-purple: #ae81ff;
|
$code-purple: #ae81ff;
|
||||||
$code-black: #272822;
|
$code-black: #272822;
|
||||||
$code-white: #f8f8f2;
|
$code-white: #f8f8f8;
|
||||||
$code-grey: #708090;
|
$code-grey: #708090;
|
||||||
$code-green: #a6e22e;
|
$code-green: #a6e22e;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<code :class="class"><slot></slot></code>
|
<code :class="cssClass"><slot></slot></code>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
export default {
|
export default {
|
||||||
props: ['lang'],
|
props: ['lang'],
|
||||||
computed: {
|
computed: {
|
||||||
class () {
|
cssClass () {
|
||||||
return `language-${this.lang}`
|
return `language-${this.lang}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-5">
|
<div class="col-md-5">
|
||||||
<p>The resulting vue-select, and it's value: <v-code lang="json">{{ install | json }}</v-code></p>
|
<p>The resulting vue-select, and it's value: <v-code lang="json">{{ install }}</v-code></p>
|
||||||
<v-select :value.sync="install" :options="['foo','bar','baz']"></v-select>
|
<v-select v-model="install" :options="['foo','bar','baz']"></v-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
<p>The <code>.sync</code> data-binding modifier is completely optional. You may use <code>value</code> without a two-way binding to preselect options.</p>
|
<p>The <code>.sync</code> data-binding modifier is completely optional. You may use <code>value</code> without a two-way binding to preselect options.</p>
|
||||||
<p>Here we have preselected 'Canada' by setting <code>syncedVal: 'Canada'</code> on the parent component. The buttons below demonstrate how you can set the <code>value</code> from the parent.</p>
|
<p>Here we have preselected 'Canada' by setting <code>syncedVal: 'Canada'</code> on the parent component. The buttons below demonstrate how you can set the <code>value</code> from the parent.</p>
|
||||||
|
|
||||||
<p>Current value: <v-code>{{ syncedVal | json }}</v-code></p>
|
<p>Current value: <v-code>{{ syncedVal }}</v-code></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
<pre><v-code lang="markup"><v-select :value.sync="syncedVal" :options="countries"></v-select></v-code></pre>
|
<pre><v-code lang="markup"><v-select :value.sync="syncedVal" :options="countries"></v-select></v-code></pre>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<v-select :options="simple" :value.sync="syncedVal"></v-select>
|
<v-select :options="simple" v-model="syncedVal"></v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -100,10 +100,10 @@
|
|||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article class="doc-row" id="ex-vuex">
|
<article class="doc-row" id="ex-vuex">
|
||||||
<h3 class="page-header">On-Change Callback <small>Vuex Compatibility</small></h3>
|
<h3 class="page-header">Change Event <small>Vuex Compatibility</small></h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<p>vue-select provides an <code>onChange</code> property that accepts a callback function. This function is passed the currently selected value(s) as it's only parameter.</p>
|
<p>vue-select provides an <code>change</code> event. This function is passed the currently selected value(s) as it's only parameter.</p>
|
||||||
<p>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.</p>
|
<p>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.</p>
|
||||||
|
|
||||||
<div class="form-inline">
|
<div class="form-inline">
|
||||||
@@ -122,7 +122,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<pre><v-code lang="markup"><v-select :on-change="consoleCallback" :options="countries"></v-select></v-code></pre>
|
<pre><v-code lang="markup"><v-select v-on:change="consoleCallback" :options="countries"></v-select></v-code></pre>
|
||||||
<pre><v-code lang="javascript">methods: {
|
<pre><v-code lang="javascript">methods: {
|
||||||
consoleCallback(val) {
|
consoleCallback(val) {
|
||||||
console.dir(JSON.stringify(val))
|
console.dir(JSON.stringify(val))
|
||||||
@@ -137,7 +137,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<ajax></ajax>
|
<!-- <ajax></ajax> -->
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -157,6 +157,7 @@
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {vSelect,vCode,InstallSnippet,Ajax},
|
components: {vSelect,vCode,InstallSnippet,Ajax},
|
||||||
|
// components: {vSelect,vCode,InstallSnippet},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
countries,
|
countries,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="github-search panel panel-default">
|
<div class="github-search panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<v-select :debounce="250" :value.sync="repo" :options="options" :on-search="getOptions" placeholder="Search GitHub Repositories..." label="full_name"></v-select>
|
<v-select :debounce="250" v-model="repo" :options="options" :on-search="getOptions" placeholder="Search GitHub Repositories..." label="full_name"></v-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body" v-if="repo">
|
<div class="panel-body" v-if="repo">
|
||||||
<img :src="repo.owner.avatar_url" alt="{{ repo.owner.login }}" class="gravatar">
|
<img :src="repo.owner.avatar_url" alt="{{ repo.owner.login }}" class="gravatar">
|
||||||
|
|||||||
+16
-14
@@ -1,16 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<h2 class="page-header">Parameters</h2>
|
<div>
|
||||||
<pre v-pre><code class="language-javascript">props: {
|
<h2 class="page-header">Parameters</h2>
|
||||||
|
<pre v-pre><code class="language-javascript">props: {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the currently selected value. Very similar to a
|
* Contains the currently selected value. Very similar to a
|
||||||
* `value` attribute on an &lt;input&gt;. In most cases, you'll want
|
* `value` attribute on an <input>. You can listen for changes
|
||||||
* to set this as a two-way binding, using :value.sync. However,
|
* using 'change' event using v-on
|
||||||
* this will not work with Vuex, in which case you'll need to use
|
|
||||||
* the onChange callback property.
|
|
||||||
* @type {Object||String||null}
|
* @type {Object||String||null}
|
||||||
*/
|
*/
|
||||||
value: {
|
value: {
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -90,16 +89,19 @@
|
|||||||
* @default {null}
|
* @default {null}
|
||||||
*/
|
*/
|
||||||
onChange: Function
|
onChange: Function
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</code></pre>
|
</code></pre>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/**
|
/**
|
||||||
* Note that this file (and anything other than src/components/Select.vue)
|
* Note that this file (and anything other than src/components/Select.vue)
|
||||||
* has nothing to do with how you use vue-select. These files are used
|
* has nothing to do with how you use vue-select. These files are used
|
||||||
* for the demo site at http://sagalbot.github.io/vue-select/. They'll
|
* for the demo site at http://sagalbot.github.io/vue-select/. They'll
|
||||||
* be moved out of this repo in the very near future to avoid confusion.
|
* be moved out of this repo in the very near future to avoid confusion.
|
||||||
*/
|
*/
|
||||||
export default {}
|
export default {}
|
||||||
</script>
|
</script>
|
||||||
@@ -113,13 +113,14 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
import GitHubSearchBasic from 'components/GitHubSearchBasic.vue'
|
|
||||||
import GitHubSearch from 'components/GitHubSearch.vue'
|
// import GitHubSearchBasic from 'docs/components/GitHubSearchBasic.vue'
|
||||||
import AjaxProps from './AjaxProps.vue'
|
// import GitHubSearch from 'docs/components/GitHubSearch.vue'
|
||||||
import AjaxExample from './AjaxExample.vue'
|
// import AjaxProps from './AjaxProps.vue'
|
||||||
|
// import AjaxExample from './AjaxExample.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {GitHubSearchBasic, GitHubSearch, AjaxProps, AjaxExample},
|
// components: {GitHubSearchBasic, GitHubSearch, AjaxProps, AjaxExample},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
basicSource: false,
|
basicSource: false,
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<p>Install from GitHub via NPM</p>
|
<div>
|
||||||
<pre><v-code lang="bash">npm install sagalbot/vue-select</v-code></pre>
|
<p>Install from GitHub via NPM</p>
|
||||||
|
<pre><v-code lang="bash">npm install sagalbot/vue-select</v-code></pre>
|
||||||
|
|
||||||
<p>To use the vue-select component in your templates, simply import it, and register it with your component.</p>
|
<p>To use the vue-select component in your templates, simply import it, and register it with your component.</p>
|
||||||
<pre><v-code lang="markup"><template>
|
<pre><v-code lang="markup"><template>
|
||||||
<div id="myApp">
|
<div id="myApp">
|
||||||
<v-select :value.sync="selected" :options="options"></v-select>
|
<v-select :value.sync="selected" :options="options"></v-select>
|
||||||
</div>
|
</div>
|
||||||
@@ -22,16 +23,19 @@
|
|||||||
}
|
}
|
||||||
</script></v-code>
|
</script></v-code>
|
||||||
</pre>
|
</pre>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script type="text/babel">
|
<script type="text/babel">
|
||||||
/**
|
/**
|
||||||
* Note that this file (and anything other than src/components/Select.vue)
|
* Note that this file (and anything other than src/components/Select.vue)
|
||||||
* has nothing to do with how you use vue-select. These files are used
|
* has nothing to do with how you use vue-select. These files are used
|
||||||
* for the demo site at http://sagalbot.github.io/vue-select/. They'll
|
* for the demo site at http://sagalbot.github.io/vue-select/. They'll
|
||||||
* be moved out of this repo in the very near future to avoid confusion.
|
* be moved out of this repo in the very near future to avoid confusion.
|
||||||
*/
|
*/
|
||||||
import vCode from '../Code.vue'
|
import vCode from '../Code.vue'
|
||||||
export default {
|
export default {
|
||||||
components: {vCode}
|
components: {
|
||||||
|
vCode
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
<meta property="og:url" content="http://sagalbot.github.io/vue-select/">
|
<meta property="og:url" content="http://sagalbot.github.io/vue-select/">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="app">
|
||||||
<div class="jumbotron jumbotron-top">
|
<div class="jumbotron jumbotron-top">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="col-md-8 col-md-offset-2">
|
<div class="col-md-8 col-md-offset-2">
|
||||||
@@ -43,12 +44,9 @@
|
|||||||
|
|
||||||
<v-select
|
<v-select
|
||||||
id="v-select"
|
id="v-select"
|
||||||
taggable
|
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
:value="selected"
|
|
||||||
:options="options"
|
:options="options"
|
||||||
:multiple="multiple"
|
multiple
|
||||||
:on-change="setSelected"
|
|
||||||
>
|
>
|
||||||
</v-select>
|
</v-select>
|
||||||
|
|
||||||
@@ -79,7 +77,8 @@
|
|||||||
<i role="presentation" class="glyphicon glyphicon-chevron-down"></i>
|
<i role="presentation" class="glyphicon glyphicon-chevron-down"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<app></app>
|
<docs></docs>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import 'prismjs'
|
import 'prismjs'
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import App from './Docs.vue'
|
import Docs from './Docs.vue'
|
||||||
import store from './vuex/store'
|
import store from './vuex/store'
|
||||||
import Resource from 'vue-resource'
|
import Resource from 'vue-resource'
|
||||||
import vSelect from '../src/components/Select.vue'
|
import vSelect from '../src/components/Select.vue'
|
||||||
import vCode from './components/Code.vue'
|
import vCode from './components/Code.vue'
|
||||||
|
import countries from './data/advanced'
|
||||||
|
|
||||||
Vue.use(Resource)
|
Vue.use(Resource)
|
||||||
|
|
||||||
@@ -23,27 +24,13 @@ import { setSelected, toggleMultiple, setPlaceholder, toggleOptionType } from '.
|
|||||||
|
|
||||||
/* eslint-disable no-new */
|
/* eslint-disable no-new */
|
||||||
new Vue({
|
new Vue({
|
||||||
el: 'body',
|
el: '#app',
|
||||||
store,
|
store,
|
||||||
components: { App },
|
components: { Docs },
|
||||||
vuex: {
|
data () {
|
||||||
getters: {
|
return {
|
||||||
placeholder (store) {
|
options: countries,
|
||||||
return store.placeholder
|
placeholder: 'Choose a country..',
|
||||||
},
|
}
|
||||||
selected (store) {
|
|
||||||
return store.selected
|
|
||||||
},
|
|
||||||
type (store) {
|
|
||||||
return store.optionType
|
|
||||||
},
|
|
||||||
options (store) {
|
|
||||||
return store.options[store.optionType]
|
|
||||||
},
|
|
||||||
multiple (store) {
|
|
||||||
return store.multiple
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: { setSelected, toggleMultiple, setPlaceholder, toggleOptionType }
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
## AJAX Remote Option Loading
|
||||||
|
|
||||||
|
|
||||||
|
The `onSearch` prop allows you to load options via ajax in a parent component when the search text is updated. It is invoked with two parameters, `search` & `loading`.
|
||||||
|
|
||||||
|
#### onSearch Callback Parameters <small>search, loading</small>
|
||||||
|
|
||||||
|
`search` is a string containing the current search text. `loading` is a function that accepts a boolean value, and is used to toggle the 'loading' class on the top-level vue-select wrapper.
|
||||||
|
|
||||||
|
#### Loading Spinner
|
||||||
|
|
||||||
|
Vue Select includes a default loading spinner that appears when the loading class is present. The `spinner` slot allows you to implement your own spinner.
|
||||||
|
|
||||||
|
<div id="spinner-example" :class="{loading:spinner}"><button class="btn btn-sm btn-default" @click="spinner = !spinner">Toggle Spinner</button>
|
||||||
|
|
||||||
|
<div class="spinner" v-show="spinner">Loading...</div>
|
||||||
|
|
||||||
|
#### Debounce Input
|
||||||
|
|
||||||
|
Vue Select also accepts a `debounce` prop that can be used to prevent `onSearch` from being called until input has completed.
|
||||||
|
|
||||||
|
#### Library Agnostic
|
||||||
|
|
||||||
|
Since Vue.js does not ship with ajax functionality as part of the core library, it's up to you to process the ajax requests in your parent component.
|
||||||
|
|
||||||
|
|
||||||
|
#### Example <small>GitHub API</small>
|
||||||
|
|
||||||
|
In this example, [Vue Resource](https://github.com/vuejs/vue-resource) is used to access the [GitHub API](https://developer.github.com/v3/).
|
||||||
|
|
||||||
|
<git-hub-search-basic></git-hub-search-basic><ajax-example></ajax-example></div>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
```html
|
||||||
|
<v-select
|
||||||
|
:debounce="250"
|
||||||
|
:on-search="getOptions"
|
||||||
|
:options="options"
|
||||||
|
placeholder="Search GitHub Repositories..."
|
||||||
|
label="full_name"
|
||||||
|
>
|
||||||
|
</v-select>
|
||||||
|
```
|
||||||
|
```js
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getOptions(search, loading) {
|
||||||
|
loading(true)
|
||||||
|
this.$http.get('https://api.github.com/search/repositories', {
|
||||||
|
q: search
|
||||||
|
}).then(resp => {
|
||||||
|
this.options = resp.data.items
|
||||||
|
loading(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
```js
|
||||||
|
/**
|
||||||
|
* Accept a callback function that will be run
|
||||||
|
* when the search text changes. The callback
|
||||||
|
* will be invoked with these parameters:
|
||||||
|
|
||||||
|
* @param {search} String Current search text
|
||||||
|
* @param {loading} Function(bool) Toggle loading class
|
||||||
|
*/
|
||||||
|
onSearch: {
|
||||||
|
type: Function,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Milliseconds to wait before invoking this.onSearch().
|
||||||
|
* Used to prevent sending an AJAX request until input
|
||||||
|
* has completed.
|
||||||
|
*/
|
||||||
|
debounce: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
### Custom Labels
|
||||||
|
|
||||||
|
By default when the `options` array contains objects, `vue-select` looks for the `label` key for display. If your data source doesn't contain that key, you can set your own using the `label` prop.
|
||||||
|
|
||||||
|
On this page, the list of countries used in the examples contains `value` and `label` properties: `{value: "CA", label: "Canada"}`. In this example, we'll display the country code instead of the label.
|
||||||
|
|
||||||
|
`<v-select label="value" :options="countries"></v-select>`
|
||||||
|
|
||||||
|
<v-select label="value" :options="countries"></v-select>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
## NPM Based WorkFlows
|
||||||
|
``` bash
|
||||||
|
$ npm install vue-select
|
||||||
|
```
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<div id="myApp">
|
||||||
|
<v-select v-model="selected" :options="options"></v-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import vSelect from 'vue-select'
|
||||||
|
export default {
|
||||||
|
components: {vSelect},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selected: null,
|
||||||
|
options: ['foo','bar','baz']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Browser Globals
|
||||||
|
|
||||||
|
`v1.3.0+` no longer requires any toolchain to use the component:
|
||||||
|
|
||||||
|
Just include `vue` & `vue-select.js` - I recommend using [unpkg.com](https://unpkg.com/#/).
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- use the latest release -->
|
||||||
|
<script src="https://unpkg.com/vue-select@latest"></script>
|
||||||
|
<!-- or point to a specific release -->
|
||||||
|
<script src="https://unpkg.com/vue-select@1.30"></script>
|
||||||
|
```
|
||||||
|
Then register the component in your javascript:
|
||||||
|
|
||||||
|
```js
|
||||||
|
Vue.component('v-select', VueSelect.VueSelect);
|
||||||
|
```
|
||||||
|
|
||||||
|
From there you can use as normal. Here's an [example on JSBin](http://jsbin.com/saxaru/5/edit?html,js,output).
|
||||||
@@ -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 v-on:change="consoleCallback" :options="countries"></v-select>
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
methods: {
|
||||||
|
consoleCallback(val) {
|
||||||
|
console.dir(JSON.stringify(val))
|
||||||
|
},
|
||||||
|
|
||||||
|
alertCallback(val) {
|
||||||
|
alert(JSON.stringify(val))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
### Reactive Options
|
||||||
|
|
||||||
|
When the list of options provided by the parent changes, vue-select will react as you'd expect.
|
||||||
|
|
||||||
|
<div style="margin-top:0;" class="radio">
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="reactive-options" v-model="reactive" :value="countries">
|
||||||
|
`<v-select :options="countries"></v-select>`
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="radio">
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="reactive-options" v-model="reactive" :value="['foo','bar','baz']">
|
||||||
|
`<v-select options="['foo','bar','baz']"></v-select>`
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<v-select :options="reactive"></v-select>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<article class="doc-row" id="ex-multiple">
|
||||||
|
|
||||||
|
### Single/Multiple Selection
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
#### Single Option Select
|
||||||
|
|
||||||
|
```html
|
||||||
|
<v-select :options="countries"></v-select>
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
#### Multiple Option Select
|
||||||
|
|
||||||
|
```html
|
||||||
|
<v-select multiple :options="countries"></v-select>
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</article>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
### Two-Way Value Syncing
|
||||||
|
|
||||||
|
The most common use case for vue-select is being able to sync the components value with a parent component. The `value` property supports two-way data binding to accomplish this. The `.sync` data-binding modifier is completely optional. You may use `value` without a two-way binding to preselect options. Here we have preselected 'Canada' by setting `syncedVal: 'Canada'` on the parent component. The buttons below demonstrate how you can set the `value` from the parent. Current value: <v-code>{{ syncedVal }}</v-code>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
`<v-select v-model="syncedVal" :options="countries"></v-select>`
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<v-select v-model="syncedVal" :options="countries"></v-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<button @click="syncedVal = 'United States'" class="btn btn-default">Set to United States</button>
|
||||||
|
<button @click="syncedVal = 'Canada'" class="btn btn-default">Set to Canada</button>
|
||||||
|
</div>
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
export const setSelected = ({ dispatch }, selected) => {
|
|
||||||
dispatch('SET_SELECTED', selected)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const toggleOptionType = ({ dispatch }) => {
|
|
||||||
dispatch('TOGGLE_OPTION_TYPE')
|
|
||||||
}
|
|
||||||
|
|
||||||
export const setPlaceholder = ({ dispatch }, placeholder) => {
|
|
||||||
dispatch('SET_PLACEHOLDER', placeholder)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const toggleMultiple = ({ dispatch }) => {
|
|
||||||
dispatch('TOGGLE_MULTIPLE')
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
import Vue from 'vue'
|
|
||||||
import Vuex from 'vuex'
|
|
||||||
|
|
||||||
Vue.use(Vuex)
|
|
||||||
Vue.config.debug = true
|
|
||||||
|
|
||||||
const state = {
|
|
||||||
selected: null,
|
|
||||||
placeholder: 'Select a Country',
|
|
||||||
multiple: true,
|
|
||||||
maxHeight: '400px',
|
|
||||||
options: {
|
|
||||||
advanced: require('../data/advanced.js'),
|
|
||||||
simple: require('../data/simple.js'),
|
|
||||||
},
|
|
||||||
optionType: 'advanced'
|
|
||||||
}
|
|
||||||
|
|
||||||
const mutations = {
|
|
||||||
SET_SELECTED (state, selected) {
|
|
||||||
state.selected = selected
|
|
||||||
},
|
|
||||||
|
|
||||||
TOGGLE_OPTION_TYPE (state) {
|
|
||||||
if( state.optionType === 'advanced' ) {
|
|
||||||
state.optionType = 'simple'
|
|
||||||
} else {
|
|
||||||
state.optionType = 'advanced'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
SET_PLACEHOLDER (state, placeholder) {
|
|
||||||
state.placeholder = placeholder
|
|
||||||
},
|
|
||||||
|
|
||||||
TOGGLE_MULTIPLE (state) {
|
|
||||||
state.multiple = ! state.multiple
|
|
||||||
},
|
|
||||||
|
|
||||||
SET_MAX_HEIGHT (state, maxHeight) {
|
|
||||||
state.maxHeight = maxHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default new Vuex.Store({
|
|
||||||
state,
|
|
||||||
mutations
|
|
||||||
})
|
|
||||||
+16
-7
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-select",
|
"name": "vue-select",
|
||||||
"version": "1.3.3",
|
"version": "2.0.0",
|
||||||
"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,
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node build/dev-server.js",
|
"dev": "node build/dev-server.js",
|
||||||
|
"dev:docs": "node build/dev-server.js --docs",
|
||||||
"build": "node build/build.js",
|
"build": "node build/build.js",
|
||||||
"lint": "eslint --ext .js,.vue src test/unit/specs",
|
"lint": "eslint --ext .js,.vue src test/unit/specs",
|
||||||
"test": "karma start test/unit/karma.conf.js --single-run",
|
"test": "karma start test/unit/karma.conf.js --single-run",
|
||||||
@@ -23,6 +24,9 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sagalbot/vue-select.git"
|
"url": "https://github.com/sagalbot/vue-select.git"
|
||||||
},
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "2.x"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-core": "^6.0.0",
|
"babel-core": "^6.0.0",
|
||||||
"babel-loader": "^6.0.0",
|
"babel-loader": "^6.0.0",
|
||||||
@@ -38,6 +42,8 @@
|
|||||||
"file-loader": "^0.8.4",
|
"file-loader": "^0.8.4",
|
||||||
"function-bind": "^1.0.2",
|
"function-bind": "^1.0.2",
|
||||||
"gh-pages": "^0.11.0",
|
"gh-pages": "^0.11.0",
|
||||||
|
"highlight.js": "^9.9.0",
|
||||||
|
"html-loader": "^0.4.4",
|
||||||
"html-webpack-plugin": "^2.8.1",
|
"html-webpack-plugin": "^2.8.1",
|
||||||
"http-proxy-middleware": "^0.15.2",
|
"http-proxy-middleware": "^0.15.2",
|
||||||
"inject-loader": "^2.0.1",
|
"inject-loader": "^2.0.1",
|
||||||
@@ -52,6 +58,7 @@
|
|||||||
"karma-spec-reporter": "0.0.26",
|
"karma-spec-reporter": "0.0.26",
|
||||||
"karma-webpack": "^1.7.0",
|
"karma-webpack": "^1.7.0",
|
||||||
"lolex": "^1.4.0",
|
"lolex": "^1.4.0",
|
||||||
|
"markdown-loader": "^0.1.7",
|
||||||
"node-sass": "^3.7.0",
|
"node-sass": "^3.7.0",
|
||||||
"ora": "^0.2.0",
|
"ora": "^0.2.0",
|
||||||
"phantomjs-prebuilt": "^2.1.3",
|
"phantomjs-prebuilt": "^2.1.3",
|
||||||
@@ -59,13 +66,15 @@
|
|||||||
"sass-loader": "^3.2.0",
|
"sass-loader": "^3.2.0",
|
||||||
"shelljs": "^0.7.0",
|
"shelljs": "^0.7.0",
|
||||||
"url-loader": "^0.5.7",
|
"url-loader": "^0.5.7",
|
||||||
"vue": "^1.0.24",
|
"vue": "^2.1.8",
|
||||||
"vue-hot-reload-api": "^1.2.0",
|
"vue-hot-reload-api": "^2.0.7",
|
||||||
"vue-html-loader": "^1.0.0",
|
"vue-html-loader": "^1.2.3",
|
||||||
"vue-loader": "^8.3.0",
|
"vue-loader": "^10.0.2",
|
||||||
"vue-resource": "^0.8.0",
|
"vue-markdown-loader": "^0.6.1",
|
||||||
|
"vue-resource": "^1.0.3",
|
||||||
"vue-style-loader": "^1.0.0",
|
"vue-style-loader": "^1.0.0",
|
||||||
"vuex": "^0.6.3",
|
"vue-template-compiler": "^2.1.8",
|
||||||
|
"vuex": "^2.1.1",
|
||||||
"webpack": "^1.12.2",
|
"webpack": "^1.12.2",
|
||||||
"webpack-dev-middleware": "^1.4.0",
|
"webpack-dev-middleware": "^1.4.0",
|
||||||
"webpack-hot-middleware": "^2.6.0",
|
"webpack-hot-middleware": "^2.6.0",
|
||||||
|
|||||||
+679
-562
File diff suppressed because it is too large
Load Diff
+8
-3
@@ -1,12 +1,17 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import vSelect from '../src/components/Select.vue'
|
import vSelect from './components/Select.vue'
|
||||||
|
import countries from 'docs/data/advanced.js'
|
||||||
|
|
||||||
Vue.component('v-select', vSelect)
|
Vue.component('v-select', vSelect)
|
||||||
|
|
||||||
Vue.config.debug = true
|
|
||||||
Vue.config.devtools = true
|
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
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
+3
-3
@@ -23,7 +23,7 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
onSearch: {
|
onSearch: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: false
|
default: function(search, loading){}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,9 +59,9 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
toggleLoading(toggle = null) {
|
toggleLoading(toggle = null) {
|
||||||
if (toggle == null) {
|
if (toggle == null) {
|
||||||
return this.loading = !this.loading
|
return this.showLoading = !this.showLoading
|
||||||
}
|
}
|
||||||
return this.loading = toggle
|
return this.showLoading = toggle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// flow
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
watch: {
|
watch: {
|
||||||
typeAheadPointer() {
|
typeAheadPointer() {
|
||||||
@@ -30,8 +32,10 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
pixelsToPointerTop() {
|
pixelsToPointerTop() {
|
||||||
let pixelsToPointerTop = 0
|
let pixelsToPointerTop = 0
|
||||||
for (let i = 0; i < this.typeAheadPointer; i++) {
|
if( this.$refs.dropdownMenu ) {
|
||||||
pixelsToPointerTop += this.$els.dropdownMenu.children[i].offsetHeight
|
for (let i = 0; i < this.typeAheadPointer; i++) {
|
||||||
|
pixelsToPointerTop += this.$refs.dropdownMenu.children[i].offsetHeight
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return pixelsToPointerTop
|
return pixelsToPointerTop
|
||||||
},
|
},
|
||||||
@@ -50,7 +54,7 @@ module.exports = {
|
|||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
pointerHeight() {
|
pointerHeight() {
|
||||||
let element = this.$els.dropdownMenu.children[this.typeAheadPointer]
|
let element = this.$refs.dropdownMenu ? this.$refs.dropdownMenu.children[this.typeAheadPointer] : false
|
||||||
return element ? element.offsetHeight : 0
|
return element ? element.offsetHeight : 0
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -60,8 +64,8 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
viewport() {
|
viewport() {
|
||||||
return {
|
return {
|
||||||
top: this.$els.dropdownMenu.scrollTop,
|
top: this.$refs.dropdownMenu ? this.$refs.dropdownMenu.scrollTop: 0,
|
||||||
bottom: this.$els.dropdownMenu.offsetHeight + this.$els.dropdownMenu.scrollTop
|
bottom: this.$refs.dropdownMenu ? this.$refs.dropdownMenu.offsetHeight + this.$refs.dropdownMenu.scrollTop : 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -71,7 +75,7 @@ module.exports = {
|
|||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
scrollTo(position) {
|
scrollTo(position) {
|
||||||
return this.$els.dropdownMenu.scrollTop = position
|
return this.$refs.dropdownMenu ? this.$refs.dropdownMenu.scrollTop = position : null
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,6 +64,9 @@ module.exports = function (config) {
|
|||||||
webpackMiddleware: {
|
webpackMiddleware: {
|
||||||
noInfo: true
|
noInfo: true
|
||||||
},
|
},
|
||||||
|
specReporter: {
|
||||||
|
suppressSkipped: true
|
||||||
|
},
|
||||||
coverageReporter: {
|
coverageReporter: {
|
||||||
dir: './coverage',
|
dir: './coverage',
|
||||||
reporters: [
|
reporters: [
|
||||||
|
|||||||
+289
-150
@@ -1,15 +1,15 @@
|
|||||||
|
// flow
|
||||||
/* global describe, it, expect */
|
/* global describe, it, expect */
|
||||||
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import vSelect from 'src/components/Select.vue'
|
import vSelect from 'src/components/Select.vue'
|
||||||
// import vSelect from '../../../dist/vue-select'
|
|
||||||
import pointerScroll from 'src/mixins/pointerScroll.js'
|
import pointerScroll from 'src/mixins/pointerScroll.js'
|
||||||
|
|
||||||
Vue.component('v-select', vSelect)
|
|
||||||
|
|
||||||
// http://vue-loader.vuejs.org/en/workflow/testing-with-mocks.html
|
// http://vue-loader.vuejs.org/en/workflow/testing-with-mocks.html
|
||||||
const Mock = require('!!vue?inject!src/components/Select.vue')
|
const Mock = require('!!vue?inject!src/components/Select.vue')
|
||||||
|
|
||||||
|
Vue.component('v-select', vSelect)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulate a DOM event.
|
* Simulate a DOM event.
|
||||||
* @param target
|
* @param target
|
||||||
@@ -25,6 +25,13 @@ function trigger(target, event, process) {
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulate a Mouse event.
|
||||||
|
* @param target
|
||||||
|
* @param event
|
||||||
|
* @param process
|
||||||
|
* @returns {Event}
|
||||||
|
*/
|
||||||
function triggerMouse(target, event, process) {
|
function triggerMouse(target, event, process) {
|
||||||
var e = document.createEvent('MouseEvent')
|
var e = document.createEvent('MouseEvent')
|
||||||
e.initEvent('event', true, true)
|
e.initEvent('event', true, true)
|
||||||
@@ -33,6 +40,13 @@ function triggerMouse(target, event, process) {
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simulate a Focus event.
|
||||||
|
* @param target
|
||||||
|
* @param event
|
||||||
|
* @param process
|
||||||
|
* @returns {Event}
|
||||||
|
*/
|
||||||
function triggerFocusEvent(target, event, process) {
|
function triggerFocusEvent(target, event, process) {
|
||||||
var e = document.createEvent('FocusEvent')
|
var e = document.createEvent('FocusEvent')
|
||||||
e.initEvent('event', true, true)
|
e.initEvent('event', true, true)
|
||||||
@@ -51,7 +65,7 @@ function searchSubmit(vm, search = false) {
|
|||||||
vm.$children[0].search = search
|
vm.$children[0].search = search
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger(vm.$children[0].$els.search, 'keyup', function (e) {
|
trigger(vm.$children[0].$refs.search, 'keyup', function (e) {
|
||||||
e.keyCode = 13
|
e.keyCode = 13
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -61,67 +75,75 @@ describe('Select.vue', () => {
|
|||||||
describe('Selecting values', () => {
|
describe('Selecting values', () => {
|
||||||
it('can accept an array with pre-selected values', () => {
|
it('can accept an array with pre-selected values', () => {
|
||||||
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" :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].value).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)', () => {
|
||||||
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" :value="value"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: {label: 'This is Foo', value: 'foo'},
|
value: {label: 'This is Foo', value: 'foo'},
|
||||||
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].value).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)', () => {
|
||||||
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" :value="value" :multiple="true"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}],
|
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'}]
|
options: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}]
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
expect(vm.$children[0].value).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', () => {
|
||||||
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" :value="value" :multiple="true"></v-select></div>',
|
||||||
data: {
|
data: {
|
||||||
value: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}],
|
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'}]
|
options: [{label: 'This is Foo', value: 'foo'}, {label: 'This is Bar', value: 'bar'}]
|
||||||
}
|
}
|
||||||
}).$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].value.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', () => {
|
||||||
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" :value="value" :multiple="true"></v-select></div>',
|
||||||
data: {
|
data: {
|
||||||
value: ['foo', 'bar'],
|
value: ['foo', 'bar'],
|
||||||
options: ['foo','bar']
|
options: ['foo','bar']
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].select('foo')
|
vm.$children[0].select('foo')
|
||||||
expect(vm.$children[0].value.length).toEqual(1)
|
expect(vm.$children[0].mutableValue.length).toEqual(1)
|
||||||
|
}),
|
||||||
|
|
||||||
|
it('can deselect an option when multiple is false', () => {
|
||||||
|
const vm = new Vue({
|
||||||
|
template: `<div><v-select :value="'foo'"></v-select></div>`,
|
||||||
|
}).$mount()
|
||||||
|
vm.$children[0].deselect('foo')
|
||||||
|
expect(vm.$children[0].mutableValue).toEqual(null)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can determine if the value prop is empty', () => {
|
it('can determine if the value prop is empty', () => {
|
||||||
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" :value="value"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: [],
|
value: [],
|
||||||
@@ -131,28 +153,28 @@ describe('Select.vue', () => {
|
|||||||
var select = vm.$children[0]
|
var select = vm.$children[0]
|
||||||
expect(select.isValueEmpty).toEqual(true)
|
expect(select.isValueEmpty).toEqual(true)
|
||||||
|
|
||||||
select.$set('value', ['one'])
|
select.select(['one'])
|
||||||
expect(select.isValueEmpty).toEqual(false)
|
expect(select.isValueEmpty).toEqual(false)
|
||||||
|
|
||||||
select.$set('value', [{l: 'f'}])
|
select.select([{l: 'f'}])
|
||||||
expect(select.isValueEmpty).toEqual(false)
|
expect(select.isValueEmpty).toEqual(false)
|
||||||
|
|
||||||
select.$set('value', 'one')
|
select.select('one')
|
||||||
expect(select.isValueEmpty).toEqual(false)
|
expect(select.isValueEmpty).toEqual(false)
|
||||||
|
|
||||||
select.$set('value', {label: 'foo', value: 'foo'})
|
select.select({label: 'foo', value: 'foo'})
|
||||||
expect(select.isValueEmpty).toEqual(false)
|
expect(select.isValueEmpty).toEqual(false)
|
||||||
|
|
||||||
select.$set('value', '')
|
select.select('')
|
||||||
expect(select.isValueEmpty).toEqual(true)
|
expect(select.isValueEmpty).toEqual(true)
|
||||||
|
|
||||||
select.$set('value', null)
|
select.select(null)
|
||||||
expect(select.isValueEmpty).toEqual(true)
|
expect(select.isValueEmpty).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should reset the selected values when the multiple property changes', (done) => {
|
it('should reset the selected values when the multiple property changes', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="multiple"></v-select></div>',
|
template: '<div><v-select :options="options" :value="value" :multiple="multiple"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: ['one'],
|
value: ['one'],
|
||||||
@@ -164,10 +186,10 @@ describe('Select.vue', () => {
|
|||||||
vm.multiple = false
|
vm.multiple = false
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].value).toEqual(null)
|
expect(vm.$children[0].mutableValue).toEqual(null)
|
||||||
vm.multiple = true
|
vm.multiple = true
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].value).toEqual([])
|
expect(vm.$children[0].mutableValue).toEqual([])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -175,20 +197,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].$set('options', ['one', 'five', 'six'])
|
vm.options = ['one', 'five', 'six']
|
||||||
expect(vm.$children[0].value).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,59 +221,99 @@ describe('Select.vue', () => {
|
|||||||
expect(vm.$children[0].isOptionSelected({label: 'one'})).toEqual(true)
|
expect(vm.$children[0].isOptionSelected({label: 'one'})).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('onChange Callback', () => {
|
it('can use v-model syntax for a two way binding to a parent component', (done) => {
|
||||||
it('can run a callback when the selection changes', (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()
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
|
||||||
|
it('can check if a string value is selected when the value is an object and multiple is true', () => {
|
||||||
|
const vm = new Vue({
|
||||||
|
template: `<div><v-select multiple :value="[{label: 'foo', value: 'bar'}]"></v-select></div>`,
|
||||||
|
}).$mount()
|
||||||
|
expect(vm.$children[0].isOptionSelected('foo')).toEqual(true)
|
||||||
|
}),
|
||||||
|
|
||||||
|
describe('change Event', () => {
|
||||||
|
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']" :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) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
spyOn(vm.$children[0], 'onChange')
|
vm.$refs.select.select('bar')
|
||||||
|
|
||||||
vm.$children[0].select('bar')
|
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].onChange).toHaveBeenCalledWith('bar')
|
expect(vm.foo).toEqual('bar')
|
||||||
vm.$children[0].select('baz')
|
done()
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
|
||||||
expect(vm.$children[0].onChange).toHaveBeenCalledWith('baz')
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should run onChange 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 v-ref:select :value="['foo']" :options="['foo','bar','baz']" multiple :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.$children[0], 'onChange')
|
vm.$refs.select.select('bar')
|
||||||
|
|
||||||
vm.$children[0].select('bar')
|
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].onChange).toHaveBeenCalledWith(['foo','bar'])
|
expect(vm.foo).toEqual(['foo','bar'])
|
||||||
vm.$children[0].select('baz')
|
done()
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
|
||||||
expect(vm.$children[0].onChange).toHaveBeenCalledWith(['foo','bar','baz'])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Filtering Options', () => {
|
||||||
|
it('should filter an array of strings', () => {
|
||||||
|
const vm = new Vue({
|
||||||
|
template: `<div><v-select ref="select" :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(['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>`,
|
||||||
|
data: {value: 'foo'}
|
||||||
|
}).$mount()
|
||||||
|
vm.$refs.select.search = 'ba'
|
||||||
|
expect(vm.$refs.select.filteredOptions).toEqual(['Bar','Baz'])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can filter an array of objects based on the objects label key', () => {
|
||||||
|
const vm = new Vue({
|
||||||
|
template: `<div><v-select ref="select" :options="[{label: 'Foo', value: 'foo'}, {label: 'Bar', value: 'bar'}, {label: 'Baz', value: 'baz'}]" v-model="value"></v-select></div>`,
|
||||||
|
data: {value: 'foo'}
|
||||||
|
}).$mount()
|
||||||
|
vm.$refs.select.search = 'ba'
|
||||||
|
expect(JSON.stringify(vm.$refs.select.filteredOptions)).toEqual(JSON.stringify([{label: 'Bar', value: 'bar'}, {label: 'Baz', value: 'baz'}]))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('Toggling Dropdown', () => {
|
describe('Toggling Dropdown', () => {
|
||||||
it('should not open the dropdown when the el is clicked but the component is disabled', (done) => {
|
it('should not open the dropdown when the el is clicked but the component is disabled', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
@@ -274,7 +336,7 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
it('should open the dropdown when the el is clicked', (done) => {
|
it('should open the dropdown when the el is clicked', (done) => {
|
||||||
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" :value="value"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: [{label: 'one'}],
|
value: [{label: 'one'}],
|
||||||
@@ -282,7 +344,7 @@ describe('Select.vue', () => {
|
|||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
vm.$children[0].toggleDropdown({target: vm.$children[0].$els.search})
|
vm.$children[0].toggleDropdown({target: vm.$children[0].$refs.search})
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].open).toEqual(true)
|
expect(vm.$children[0].open).toEqual(true)
|
||||||
@@ -297,20 +359,20 @@ describe('Select.vue', () => {
|
|||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
spyOn(vm.$children[0].$els.search, 'blur')
|
spyOn(vm.$children[0].$refs.search, 'blur')
|
||||||
|
|
||||||
vm.$children[0].open = true
|
vm.$children[0].open = true
|
||||||
vm.$children[0].toggleDropdown({target: vm.$children[0].$el})
|
vm.$children[0].toggleDropdown({target: vm.$children[0].$el})
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].$els.search.blur).toHaveBeenCalled()
|
expect(vm.$children[0].$refs.search.blur).toHaveBeenCalled()
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should close the dropdown on search blur', () => {
|
it('should close the dropdown on search blur', () => {
|
||||||
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 :value="value"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: [{label: 'one'}],
|
value: [{label: 'one'}],
|
||||||
@@ -319,30 +381,55 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
vm.$children[0].open = true
|
vm.$children[0].open = true
|
||||||
triggerFocusEvent(vm.$children[0].$els.toggle, 'blur')
|
triggerFocusEvent(vm.$children[0].$refs.toggle, 'blur')
|
||||||
expect(vm.$children[0].open).toEqual(true)
|
expect(vm.$children[0].open).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('will close the dropdown and emit the search:blur event from onSearchBlur', () => {
|
||||||
|
const vm = new Vue({
|
||||||
|
template: '<div><v-select></v-select></div>',
|
||||||
|
}).$mount()
|
||||||
|
|
||||||
|
spyOn(vm.$children[0], '$emit')
|
||||||
|
vm.$children[0].open = true
|
||||||
|
vm.$children[0].onSearchBlur()
|
||||||
|
|
||||||
|
expect(vm.$children[0].open).toEqual(false)
|
||||||
|
expect(vm.$children[0].$emit).toHaveBeenCalledWith('search:blur')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('will open the dropdown and emit the search:focus event from onSearchFocus', () => {
|
||||||
|
const vm = new Vue({
|
||||||
|
template: '<div><v-select></v-select></div>',
|
||||||
|
}).$mount()
|
||||||
|
|
||||||
|
spyOn(vm.$children[0], '$emit')
|
||||||
|
vm.$children[0].onSearchFocus()
|
||||||
|
|
||||||
|
expect(vm.$children[0].open).toEqual(true)
|
||||||
|
expect(vm.$children[0].$emit).toHaveBeenCalledWith('search:focus')
|
||||||
|
})
|
||||||
|
|
||||||
it('will close the dropdown on escape, if search is empty', (done) => {
|
it('will close the dropdown on escape, if search is empty', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select></v-select></div>',
|
template: '<div><v-select></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
spyOn(vm.$children[0].$els.search, 'blur')
|
spyOn(vm.$children[0].$refs.search, 'blur')
|
||||||
|
|
||||||
vm.$children[0].open = true
|
vm.$children[0].open = true
|
||||||
vm.$children[0].onEscape()
|
vm.$children[0].onEscape()
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].$els.search.blur).toHaveBeenCalled()
|
expect(vm.$children[0].$refs.search.blur).toHaveBeenCalled()
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should remove existing search text on escape keyup', () => {
|
it('should remove existing search text on escape keyup', () => {
|
||||||
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 :value="value"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: [{label: 'one'}],
|
value: [{label: 'one'}],
|
||||||
@@ -393,7 +480,7 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
vm.$children[0].typeAheadPointer = 1
|
vm.$children[0].typeAheadPointer = 1
|
||||||
|
|
||||||
trigger(vm.$children[0].$els.search, 'keydown', (e) => e.keyCode = 38)
|
trigger(vm.$children[0].$refs.search, 'keydown', (e) => e.keyCode = 38)
|
||||||
expect(vm.$children[0].typeAheadPointer).toEqual(0)
|
expect(vm.$children[0].typeAheadPointer).toEqual(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -407,7 +494,7 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
vm.$children[0].typeAheadPointer = 1
|
vm.$children[0].typeAheadPointer = 1
|
||||||
trigger(vm.$children[0].$els.search, 'keydown', (e) => e.keyCode = 40)
|
trigger(vm.$children[0].$refs.search, 'keydown', (e) => e.keyCode = 40)
|
||||||
expect(vm.$children[0].typeAheadPointer).toEqual(2)
|
expect(vm.$children[0].typeAheadPointer).toEqual(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -437,7 +524,7 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
vm.$children[0].typeAheadPointer = 1
|
vm.$children[0].typeAheadPointer = 1
|
||||||
spyOn(vm.$children[0], 'maybeAdjustScroll')
|
spyOn(vm.$children[0], 'maybeAdjustScroll')
|
||||||
trigger(vm.$children[0].$els.search, 'keydown', (e) => e.keyCode = 38)
|
trigger(vm.$children[0].$refs.search, 'keydown', (e) => e.keyCode = 38)
|
||||||
expect(vm.$children[0].maybeAdjustScroll).toHaveBeenCalled()
|
expect(vm.$children[0].maybeAdjustScroll).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -451,7 +538,7 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
spyOn(vm.$children[0], 'maybeAdjustScroll')
|
spyOn(vm.$children[0], 'maybeAdjustScroll')
|
||||||
trigger(vm.$children[0].$els.search, 'keydown', (e) => e.keyCode = 40)
|
trigger(vm.$children[0].$refs.search, 'keydown', (e) => e.keyCode = 40)
|
||||||
expect(vm.$children[0].maybeAdjustScroll).toHaveBeenCalled()
|
expect(vm.$children[0].maybeAdjustScroll).toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -496,21 +583,26 @@ describe('Select.vue', () => {
|
|||||||
expect(vm.$children[0].scrollTo).toHaveBeenCalledWith(1)
|
expect(vm.$children[0].scrollTo).toHaveBeenCalledWith(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should scroll down if the pointer is below the current viewport bounds', () => {
|
/**
|
||||||
|
* @link https://github.com/vuejs/vue-loader/issues/434
|
||||||
|
* @todo vue-loader/inject-loader fails when used twice in the same file,
|
||||||
|
* so the mock here is abastracted to a separate file.
|
||||||
|
*/
|
||||||
|
xit('should scroll down if the pointer is below the current viewport bounds', () => {
|
||||||
let methods = Object.assign(pointerScroll.methods, {
|
let methods = Object.assign(pointerScroll.methods, {
|
||||||
pixelsToPointerBottom() {
|
pixelsToPointerBottom() {
|
||||||
return 2
|
return 2
|
||||||
},
|
},
|
||||||
viewport() {
|
viewport() {
|
||||||
return {top: 0, bottom: 1}
|
return {top: 0, bottom: 1}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
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}
|
'../mixins/pointerScroll': {methods}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
@@ -523,19 +615,23 @@ describe('Select.vue', () => {
|
|||||||
describe('Measuring pixel distances', () => {
|
describe('Measuring pixel distances', () => {
|
||||||
it('should calculate pointerHeight as the offsetHeight of the pointer element if it exists', () => {
|
it('should calculate pointerHeight as the offsetHeight of the pointer element if it exists', () => {
|
||||||
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: {vSelect},
|
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
// Fresh instances start with the pointer at -1
|
// dropdown must be open for $refs to exist
|
||||||
vm.$children[0].typeAheadPointer = -1
|
vm.$children[0].open = true
|
||||||
expect(vm.$children[0].pointerHeight()).toEqual(0)
|
|
||||||
|
|
||||||
vm.$children[0].typeAheadPointer = 100
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].pointerHeight()).toEqual(0)
|
// Fresh instances start with the pointer at -1
|
||||||
|
vm.$children[0].typeAheadPointer = -1
|
||||||
|
expect(vm.$children[0].pointerHeight()).toEqual(0)
|
||||||
|
|
||||||
vm.$children[0].typeAheadPointer = 1
|
vm.$children[0].typeAheadPointer = 100
|
||||||
expect(vm.$children[0].pointerHeight()).toEqual(vm.$children[0].$els.dropdownMenu.children[1].offsetHeight)
|
expect(vm.$children[0].pointerHeight()).toEqual(0)
|
||||||
|
|
||||||
|
vm.$children[0].typeAheadPointer = 1
|
||||||
|
expect(vm.$children[0].pointerHeight()).toEqual(vm.$children[0].$refs.dropdownMenu.children[1].offsetHeight)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -543,16 +639,16 @@ 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'],
|
||||||
options: ['one', 'two', 'three']
|
options: ['one', 'two', 'three']
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].$els.toggle.querySelector('.close').click()
|
vm.$children[0].$refs.toggle.querySelector('.close').click()
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].value).toEqual([])
|
expect(vm.$children[0].mutableValue).toEqual([])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -560,7 +656,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'],
|
||||||
@@ -569,13 +665,13 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].maybeDeleteValue()
|
vm.$children[0].maybeDeleteValue()
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].value).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',
|
||||||
@@ -584,7 +680,7 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
vm.$children[0].maybeDeleteValue()
|
vm.$children[0].maybeDeleteValue()
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].value).toEqual(null)
|
expect(vm.$children[0].mutableValue).toEqual(null)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -592,14 +688,14 @@ 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'}],
|
||||||
options: [{name: 'Foo'}, {name: 'Baz'}]
|
options: [{name: 'Foo'}, {name: 'Baz'}]
|
||||||
}
|
}
|
||||||
}).$mount()
|
}).$mount()
|
||||||
expect(vm.$children[0].$els.toggle.querySelector('.selected-tag').textContent).toContain('Baz')
|
expect(vm.$children[0].$refs.toggle.querySelector('.selected-tag').textContent).toContain('Baz')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should display a placeholder if the value is empty', (done) => {
|
it('should display a placeholder if the value is empty', (done) => {
|
||||||
@@ -612,20 +708,18 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
expect(vm.$children[0].searchPlaceholder).toEqual('foo')
|
expect(vm.$children[0].searchPlaceholder).toEqual('foo')
|
||||||
vm.$children[0].value = {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')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('When Tagging Is Enabled', () => {
|
describe('When Tagging Is Enabled', () => {
|
||||||
it('can determine if a given option string already exists', () => {
|
it('can determine if a given option string already exists', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select v-ref:select :options="options" taggable></v-select></div>',
|
template: '<div><v-select ref="select" :options="options" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
options: ['one', 'two']
|
options: ['one', 'two']
|
||||||
@@ -638,7 +732,7 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
it('can determine if a given option object already exists', () => {
|
it('can determine if a given option object already exists', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select v-ref:select :options="options" taggable></v-select></div>',
|
template: '<div><v-select ref="select" :options="options" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
options: [{label: 'one'}, {label: 'two'}]
|
options: [{label: 'one'}, {label: 'two'}]
|
||||||
@@ -651,7 +745,7 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
it('can determine if a given option object already exists when using custom labels', () => {
|
it('can determine if a given option object already exists when using custom labels', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select v-ref:select :options="options" label="foo" taggable></v-select></div>',
|
template: '<div><v-select ref="select" :options="options" label="foo" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
options: [{foo: 'one'}, {foo: 'two'}]
|
options: [{foo: 'one'}, {foo: 'two'}]
|
||||||
@@ -664,7 +758,7 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
it('can add the current search text as the first item in the options list', () => {
|
it('can add the current search text as the first item in the options list', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true" taggable></v-select></div>',
|
template: '<div><v-select :options="options" :value="value" :multiple="true" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: ['one'],
|
value: ['one'],
|
||||||
@@ -678,7 +772,7 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
it('can select the current search text as a string', (done) => {
|
it('can select the current search text as a string', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true" taggable></v-select></div>',
|
template: '<div><v-select :options="options" :value="value" :multiple="true" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: ['one'],
|
value: ['one'],
|
||||||
@@ -688,14 +782,14 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
searchSubmit(vm, 'three')
|
searchSubmit(vm, 'three')
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].value).toEqual(['one', 'three'])
|
expect(vm.$children[0].mutableValue).toEqual(['one', 'three'])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can select the current search text as an object', (done) => {
|
it('can select the current search text as an object', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true" taggable></v-select></div>',
|
template: '<div><v-select :options="options" :value="value" :multiple="true" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: [{label: 'one'}],
|
value: [{label: 'one'}],
|
||||||
@@ -705,14 +799,14 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
searchSubmit(vm, 'two')
|
searchSubmit(vm, 'two')
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].value).toEqual([{label: 'one'}, {label: 'two'}])
|
expect(vm.$children[0].mutableValue).toEqual([{label: 'one'}, {label: 'two'}])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should add a freshly created option/tag to the options list when pushTags is true', () => {
|
it('should add a freshly created option/tag to the options list when pushTags is true', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" push-tags :value.sync="value" :multiple="true" taggable></v-select></div>',
|
template: '<div><v-select :options="options" push-tags :value="value" :multiple="true" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: ['one'],
|
value: ['one'],
|
||||||
@@ -721,12 +815,12 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
searchSubmit(vm, 'three')
|
searchSubmit(vm, 'three')
|
||||||
expect(vm.$children[0].options).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', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true" :taggable="true"></v-select></div>',
|
template: '<div><v-select :options="options" :value="value" :multiple="true" :taggable="true"></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: ['one'],
|
value: ['one'],
|
||||||
@@ -735,14 +829,13 @@ describe('Select.vue', () => {
|
|||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
searchSubmit(vm, 'three')
|
searchSubmit(vm, 'three')
|
||||||
expect(vm.$children[0].options).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) => {
|
||||||
let two = 'two'
|
let two = 'two'
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true" taggable></v-select></div>',
|
template: '<div><v-select :options="options" :value="value" :multiple="true" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
|
||||||
data: {
|
data: {
|
||||||
value: null,
|
value: null,
|
||||||
options: ['one', two]
|
options: ['one', two]
|
||||||
@@ -753,7 +846,7 @@ describe('Select.vue', () => {
|
|||||||
searchSubmit(vm)
|
searchSubmit(vm)
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].value[0]).toBe(two)
|
expect(vm.$children[0].mutableValue[0]).toBe(two)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -762,7 +855,6 @@ describe('Select.vue', () => {
|
|||||||
let two = {label: 'two'}
|
let two = {label: 'two'}
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" taggable></v-select></div>',
|
template: '<div><v-select :options="options" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
|
||||||
data: {
|
data: {
|
||||||
options: [{label: 'one'}, two]
|
options: [{label: 'one'}, two]
|
||||||
}
|
}
|
||||||
@@ -775,80 +867,127 @@ 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].value.label).toBe(two.label)
|
expect(vm.$children[0].mutableValue.label).toBe(two.label)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not reset the selected value when the options property changes', (done) => {
|
it('should not reset the selected value when the options property changes', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" :multiple="true" taggable></v-select></div>',
|
template: '<div><v-select :options="options" :value="value" :multiple="true" taggable></v-select></div>',
|
||||||
components: {vSelect},
|
components: {vSelect},
|
||||||
data: {
|
data: {
|
||||||
value: [{label: 'one'}],
|
value: [{label: 'one'}],
|
||||||
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].value).toEqual([{label: 'one'}])
|
expect(vm.$children[0].mutableValue).toEqual([{label: 'one'}])
|
||||||
done()
|
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>`,
|
||||||
|
}).$mount()
|
||||||
|
vm.$refs.select.search = 'one'
|
||||||
|
searchSubmit(vm)
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
expect(vm.$refs.select.mutableValue).toEqual(['one'])
|
||||||
|
expect(vm.$refs.select.search).toEqual('')
|
||||||
|
vm.$refs.select.search = 'one'
|
||||||
|
searchSubmit(vm)
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
expect(vm.$refs.select.mutableValue).toEqual([])
|
||||||
|
expect(vm.$refs.select.search).toEqual('')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not allow duplicate tags when using object options', (done) => {
|
||||||
|
const vm = new Vue({
|
||||||
|
template: `<div><v-select ref="select" taggable multiple></v-select></div>`,
|
||||||
|
}).$mount()
|
||||||
|
vm.$refs.select.search = 'one'
|
||||||
|
searchSubmit(vm)
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
expect(vm.$refs.select.mutableValue).toEqual(['one'])
|
||||||
|
expect(vm.$refs.select.search).toEqual('')
|
||||||
|
vm.$refs.select.search = 'one'
|
||||||
|
searchSubmit(vm)
|
||||||
|
Vue.nextTick(() => {
|
||||||
|
expect(vm.$refs.select.mutableValue).toEqual([])
|
||||||
|
expect(vm.$refs.select.search).toEqual('')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Asynchronous Loading', () => {
|
describe('Asynchronous Loading', () => {
|
||||||
it('can toggle the loading class', () => {
|
it('can toggle the loading class', () => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select v-ref:select></v-select></div>',
|
template: '<div><v-select ref="select"></v-select></div>',
|
||||||
}).$mount()
|
}).$mount()
|
||||||
|
|
||||||
vm.$refs.select.toggleLoading()
|
vm.$refs.select.toggleLoading()
|
||||||
expect(vm.$refs.select.loading).toEqual(true)
|
expect(vm.$refs.select.showLoading).toEqual(true)
|
||||||
|
|
||||||
vm.$refs.select.toggleLoading(true)
|
vm.$refs.select.toggleLoading(true)
|
||||||
expect(vm.$refs.select.loading).toEqual(true)
|
expect(vm.$refs.select.showLoading).toEqual(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
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 v-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()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
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 v-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()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can set loading to false from the onSearch callback', (done) => {
|
it('can set loading to false from the onSearch callback', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select loading v-ref:select :on-search="foo"></v-select></div>',
|
template: '<div><v-select loading ref="select" :on-search="foo"></v-select></div>',
|
||||||
methods: {
|
methods: {
|
||||||
foo(search, loading) {
|
foo(search, loading) {
|
||||||
loading(false)
|
loading(false)
|
||||||
@@ -858,14 +997,14 @@ describe('Select.vue', () => {
|
|||||||
|
|
||||||
vm.$refs.select.search = 'foo'
|
vm.$refs.select.search = 'foo'
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$refs.select.loading).toEqual(false)
|
expect(vm.$refs.select.showLoading).toEqual(false)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can set loading to true from the onSearch callback', (done) => {
|
it('can set loading to true from the onSearch callback', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select loading v-ref:select :on-search="foo"></v-select></div>',
|
template: '<div><v-select loading ref="select" :on-search="foo"></v-select></div>',
|
||||||
methods: {
|
methods: {
|
||||||
foo(search, loading) {
|
foo(search, loading) {
|
||||||
loading(true)
|
loading(true)
|
||||||
@@ -877,7 +1016,7 @@ describe('Select.vue', () => {
|
|||||||
select.onSearch(select.search, select.toggleLoading)
|
select.onSearch(select.search, select.toggleLoading)
|
||||||
|
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$refs.select.loading).toEqual(true)
|
expect(vm.$refs.select.showLoading).toEqual(true)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -886,31 +1025,31 @@ describe('Select.vue', () => {
|
|||||||
describe('Reset on options change', () => {
|
describe('Reset on options change', () => {
|
||||||
it('should not reset the selected value by default when the options property changes', (done) => {
|
it('should not reset the selected value by default when the options property changes', (done) => {
|
||||||
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" :value="value"></v-select></div>',
|
||||||
data: {
|
data: {
|
||||||
value: 'one',
|
value: 'one',
|
||||||
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].value).toEqual('one')
|
expect(vm.$children[0].mutableValue).toEqual('one')
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should reset the selected value when the options property changes', (done) => {
|
it('should reset the selected value when the options property changes', (done) => {
|
||||||
const vm = new Vue({
|
const vm = new Vue({
|
||||||
template: '<div><v-select :options="options" :value.sync="value" reset-on-options-change></v-select></div>',
|
template: '<div><v-select :options="options" :value="value" reset-on-options-change></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 = ['four', 'five', 'six']
|
vm.$children[0].mutableOptions = ['four', 'five', 'six']
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
expect(vm.$children[0].value).toEqual(null)
|
expect(vm.$children[0].mutableValue).toEqual(null)
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user