vue-multiselect
Advanced tools
Comparing version 1.0.0-beta.1 to 1.0.1
@@ -13,3 +13,3 @@ const webpack = require('webpack') | ||
publicPath: config.bundle.assetsPublicPath, | ||
filename: 'vue-multiselect.js', | ||
filename: 'vue-multiselect.min.js', | ||
library: 'VueMultiselect', | ||
@@ -16,0 +16,0 @@ libraryTarget: 'umd' |
@@ -1,2 +0,2 @@ | ||
import { deepClone } from './utils' | ||
import deepClone from './utils' | ||
@@ -8,3 +8,3 @@ module.exports = { | ||
isOpen: false, | ||
value: [] | ||
value: this.selected ? deepClone(this.selected) : this.multiple ? [] : null | ||
} | ||
@@ -33,3 +33,3 @@ }, | ||
/** | ||
* Required. Presets the selected options. Add `.sync` to | ||
* Presets the selected options. Add `.sync` to | ||
* update parent value. If this.onChange callback is present, | ||
@@ -40,5 +40,3 @@ * this will not update. In that case, the parent is responsible | ||
*/ | ||
selected: { | ||
required: true | ||
}, | ||
selected: {}, | ||
/** | ||
@@ -117,12 +115,2 @@ * Key to compare objects | ||
/** | ||
* Value that indicates if the dropdown has been used. | ||
* Useful for validation. | ||
* @default false | ||
* @type {Boolean} | ||
*/ | ||
touched: { | ||
type: Boolean, | ||
default: false | ||
}, | ||
/** | ||
* Reset this.value, this.search, this.selected after this.value changes. | ||
@@ -194,7 +182,2 @@ * Useful if want to create a stateless dropdown, that fires the this.onChange | ||
created () { | ||
if (!this.selected) { | ||
this.$set('value', this.multiple ? [] : null) | ||
} else { | ||
this.value = deepClone(this.selected) | ||
} | ||
if (this.searchable) this.adjustSearch() | ||
@@ -227,2 +210,5 @@ }, | ||
: this.options | ||
}, | ||
currentOptionLabel () { | ||
return this.getOptionLabel(this.value) | ||
} | ||
@@ -240,3 +226,6 @@ }, | ||
'search' () { | ||
this.$emit('search-change', this.search, this.id) | ||
/* istanbul ignore else */ | ||
if (this.search !== this.currentOptionLabel) { | ||
this.$emit('search-change', this.search, this.id) | ||
} | ||
}, | ||
@@ -386,12 +375,13 @@ 'selected' (newVal, oldVal) { | ||
/* istanbul ignore else */ | ||
if (!this.isOpen) { | ||
this.isOpen = true | ||
/* istanbul ignore else */ | ||
if (this.searchable) { | ||
this.search = '' | ||
this.$els.search.focus() | ||
} else { | ||
this.$el.focus() | ||
} | ||
if (this.isOpen) return | ||
this.isOpen = true | ||
/* istanbul ignore else */ | ||
if (this.searchable) { | ||
this.search = '' | ||
this.$els.search.focus() | ||
} else { | ||
this.$el.focus() | ||
} | ||
this.$emit('open', this.id) | ||
}, | ||
@@ -407,3 +397,2 @@ /** | ||
this.isOpen = false | ||
this.touched = true | ||
/* istanbul ignore else */ | ||
@@ -416,2 +405,3 @@ if (this.searchable) { | ||
} | ||
this.$emit('close', deepClone(this.value), this.id) | ||
}, | ||
@@ -427,3 +417,3 @@ /** | ||
? '' | ||
: this.getOptionLabel(this.value) | ||
: this.currentOptionLabel | ||
}, | ||
@@ -430,0 +420,0 @@ /** |
module.exports = { | ||
data () { | ||
return { | ||
pointer: 0 | ||
pointer: 0, | ||
visibleElements: this.maxHeight / 40 | ||
} | ||
@@ -18,2 +19,7 @@ }, | ||
}, | ||
computed: { | ||
pointerPosition () { | ||
return this.pointer * 40 | ||
} | ||
}, | ||
watch: { | ||
@@ -34,6 +40,4 @@ 'filteredOptions' () { | ||
this.pointer++ | ||
var pointerPosition = this.pointer * 40 | ||
var visibleElements = this.maxHeight / 40 | ||
if (this.$els.list.scrollTop <= pointerPosition - visibleElements * 40) { | ||
this.$els.list.scrollTop = pointerPosition - (visibleElements - 1) * 40 | ||
if (this.$els.list.scrollTop <= this.pointerPosition - this.visibleElements * 40) { | ||
this.$els.list.scrollTop = this.pointerPosition - (this.visibleElements - 1) * 40 | ||
} | ||
@@ -45,5 +49,4 @@ } | ||
this.pointer-- | ||
var pointerPosition = this.pointer * 40 | ||
if (this.$els.list.scrollTop >= pointerPosition) { | ||
this.$els.list.scrollTop = pointerPosition | ||
if (this.$els.list.scrollTop >= this.pointerPosition) { | ||
this.$els.list.scrollTop = this.pointerPosition | ||
} | ||
@@ -50,0 +53,0 @@ } |
@@ -6,3 +6,3 @@ /** | ||
*/ | ||
export function deepClone (obj) { | ||
const deepClone = function (obj) { | ||
if (Array.isArray(obj)) { | ||
@@ -22,1 +22,3 @@ return obj.map(deepClone) | ||
} | ||
module.exports = deepClone |
{ | ||
"name": "vue-multiselect", | ||
"version": "1.0.0-beta.1", | ||
"version": "1.0.1", | ||
"description": "Multiselect component for vue.js", | ||
@@ -8,6 +8,6 @@ "author": "Damian Dulisz <damian.dulisz@monterail.com>", | ||
"license": "MIT", | ||
"main": "lib/vue-multiselect.js", | ||
"jsnext:main": "lib/vue-multiselect.js", | ||
"main": "lib/vue-multiselect.min.js", | ||
"jsnext:main": "lib/vue-multiselect.min.js", | ||
"jspm": { | ||
"main": "lib/vue-multiselect.js", | ||
"main": "lib/vue-multiselect.min.js", | ||
"registry": "npm", | ||
@@ -14,0 +14,0 @@ "format": "esm" |
@@ -37,2 +37,4 @@ # vue-multiselect ![Build Status](https://circleci.com/gh/monterail/vue-multiselect/tree/master.svg?style=shield&circle-token=5c931ff28fd12587610f835472becdd514d09cef) | ||
> **It is very important not to mix `.sync` with `:on-change` prop. You have to either choose two-way binding or one way binding with `:on-change` callback as a way to update the `:selected` value** | ||
``` javascript | ||
@@ -68,9 +70,5 @@ import Multiselect from 'vue-multiselect' | ||
* Option grouping | ||
* Better mobile support | ||
* Stateless dropdowns (with no selected prop, just action pickers / search boxes) | ||
* RTL support, accessibility | ||
* 1.0 Release – Event based, deprecate two-way binding, make it easy to migrate to Vue 2.0 | ||
* Examples of custom components / templates ready to use in project | ||
* Reworking the documentation to include much more examples and use cases | ||
* Fix problem with not counting the height of the option element when creating a custom element. This is important for scrolling the options viewport when using highlighting pointer. | ||
* Better documentation | ||
@@ -77,0 +75,0 @@ ## Examples |
@@ -9,5 +9,6 @@ /*! | ||
import pointerMixin from './pointerMixin' | ||
import deepClone from './utils' | ||
export default Multiselect | ||
export { Multiselect, multiselectMixin, pointerMixin } | ||
export { Multiselect, multiselectMixin, pointerMixin, deepClone } |
@@ -1,2 +0,2 @@ | ||
import { deepClone } from './utils' | ||
import deepClone from './utils' | ||
@@ -8,3 +8,3 @@ module.exports = { | ||
isOpen: false, | ||
value: [] | ||
value: this.selected ? deepClone(this.selected) : this.multiple ? [] : null | ||
} | ||
@@ -33,3 +33,3 @@ }, | ||
/** | ||
* Required. Presets the selected options. Add `.sync` to | ||
* Presets the selected options. Add `.sync` to | ||
* update parent value. If this.onChange callback is present, | ||
@@ -40,5 +40,3 @@ * this will not update. In that case, the parent is responsible | ||
*/ | ||
selected: { | ||
required: true | ||
}, | ||
selected: {}, | ||
/** | ||
@@ -117,12 +115,2 @@ * Key to compare objects | ||
/** | ||
* Value that indicates if the dropdown has been used. | ||
* Useful for validation. | ||
* @default false | ||
* @type {Boolean} | ||
*/ | ||
touched: { | ||
type: Boolean, | ||
default: false | ||
}, | ||
/** | ||
* Reset this.value, this.search, this.selected after this.value changes. | ||
@@ -194,7 +182,2 @@ * Useful if want to create a stateless dropdown, that fires the this.onChange | ||
created () { | ||
if (!this.selected) { | ||
this.$set('value', this.multiple ? [] : null) | ||
} else { | ||
this.value = deepClone(this.selected) | ||
} | ||
if (this.searchable) this.adjustSearch() | ||
@@ -227,2 +210,5 @@ }, | ||
: this.options | ||
}, | ||
currentOptionLabel () { | ||
return this.getOptionLabel(this.value) | ||
} | ||
@@ -240,3 +226,6 @@ }, | ||
'search' () { | ||
this.$emit('search-change', this.search, this.id) | ||
/* istanbul ignore else */ | ||
if (this.search !== this.currentOptionLabel) { | ||
this.$emit('search-change', this.search, this.id) | ||
} | ||
}, | ||
@@ -386,12 +375,13 @@ 'selected' (newVal, oldVal) { | ||
/* istanbul ignore else */ | ||
if (!this.isOpen) { | ||
this.isOpen = true | ||
/* istanbul ignore else */ | ||
if (this.searchable) { | ||
this.search = '' | ||
this.$els.search.focus() | ||
} else { | ||
this.$el.focus() | ||
} | ||
if (this.isOpen) return | ||
this.isOpen = true | ||
/* istanbul ignore else */ | ||
if (this.searchable) { | ||
this.search = '' | ||
this.$els.search.focus() | ||
} else { | ||
this.$el.focus() | ||
} | ||
this.$emit('open', this.id) | ||
}, | ||
@@ -407,3 +397,2 @@ /** | ||
this.isOpen = false | ||
this.touched = true | ||
/* istanbul ignore else */ | ||
@@ -416,2 +405,3 @@ if (this.searchable) { | ||
} | ||
this.$emit('close', deepClone(this.value), this.id) | ||
}, | ||
@@ -427,3 +417,3 @@ /** | ||
? '' | ||
: this.getOptionLabel(this.value) | ||
: this.currentOptionLabel | ||
}, | ||
@@ -430,0 +420,0 @@ /** |
module.exports = { | ||
data () { | ||
return { | ||
pointer: 0 | ||
pointer: 0, | ||
visibleElements: this.maxHeight / 40 | ||
} | ||
@@ -18,2 +19,7 @@ }, | ||
}, | ||
computed: { | ||
pointerPosition () { | ||
return this.pointer * 40 | ||
} | ||
}, | ||
watch: { | ||
@@ -34,6 +40,4 @@ 'filteredOptions' () { | ||
this.pointer++ | ||
var pointerPosition = this.pointer * 40 | ||
var visibleElements = this.maxHeight / 40 | ||
if (this.$els.list.scrollTop <= pointerPosition - visibleElements * 40) { | ||
this.$els.list.scrollTop = pointerPosition - (visibleElements - 1) * 40 | ||
if (this.$els.list.scrollTop <= this.pointerPosition - this.visibleElements * 40) { | ||
this.$els.list.scrollTop = this.pointerPosition - (this.visibleElements - 1) * 40 | ||
} | ||
@@ -45,5 +49,4 @@ } | ||
this.pointer-- | ||
var pointerPosition = this.pointer * 40 | ||
if (this.$els.list.scrollTop >= pointerPosition) { | ||
this.$els.list.scrollTop = pointerPosition | ||
if (this.$els.list.scrollTop >= this.pointerPosition) { | ||
this.$els.list.scrollTop = this.pointerPosition | ||
} | ||
@@ -50,0 +53,0 @@ } |
@@ -6,3 +6,3 @@ /** | ||
*/ | ||
export function deepClone (obj) { | ||
const deepClone = function (obj) { | ||
if (Array.isArray(obj)) { | ||
@@ -22,1 +22,3 @@ return obj.map(deepClone) | ||
} | ||
module.exports = deepClone |
@@ -7,7 +7,8 @@ import Vue from 'vue' | ||
describe('@update', () => { | ||
it('should be called whenever the value changes passing the new value', () => { | ||
it('should be called whenever the value changes passing the new value and id', () => { | ||
let eventsLog = [] | ||
let calledId = null | ||
const vmSingle = new Vue({ | ||
template: '<multiselect :selected="value" :options="source" @update="onUpdate"></multiselect>', | ||
template: '<multiselect :selected="value" :options="source" @update="onUpdate" id="single"></multiselect>', | ||
components: { Multiselect }, | ||
@@ -19,3 +20,4 @@ data: { | ||
methods: { | ||
onUpdate (value) { | ||
onUpdate (value, id) { | ||
calledId = id | ||
eventsLog.push(value) | ||
@@ -27,3 +29,3 @@ } | ||
const vmMulti = new Vue({ | ||
template: '<multiselect :selected="value" :options="source" @update="onUpdate" :multiple="true"></multiselect>', | ||
template: '<multiselect :selected="value" :options="source" @update="onUpdate" :multiple="true" id="multi"></multiselect>', | ||
components: { Multiselect }, | ||
@@ -35,3 +37,4 @@ data: { | ||
methods: { | ||
onUpdate (value) { | ||
onUpdate (value, id) { | ||
calledId = id | ||
eventsLog.push(value) | ||
@@ -44,2 +47,3 @@ } | ||
expect(eventsLog[0]).to.deep.equal('1') | ||
expect(calledId).to.deep.equal('single') | ||
vmSingle.$children[0].select(vmSingle.source[1]) | ||
@@ -50,2 +54,3 @@ expect(eventsLog[1]).to.deep.equal('2') | ||
vmMulti.$children[0].select(vmMulti.source[0]) | ||
expect(calledId).to.deep.equal('multi') | ||
expect(eventsLog[3]).to.deep.equal(['1']) | ||
@@ -65,7 +70,8 @@ vmMulti.$children[0].select(vmMulti.source[1]) | ||
describe('@select', () => { | ||
it('should be called after each select passing the selected option', () => { | ||
it('should be called after each select passing the selected option and id', () => { | ||
let eventsLog = [] | ||
let calledId = null | ||
const vmSingle = new Vue({ | ||
template: '<multiselect :selected="value" :options="source" @select="onSelect"></multiselect>', | ||
template: '<multiselect :selected="value" :options="source" @select="onSelect" id="single"></multiselect>', | ||
components: { Multiselect }, | ||
@@ -77,3 +83,4 @@ data: { | ||
methods: { | ||
onSelect (option) { | ||
onSelect (option, id) { | ||
calledId = id | ||
eventsLog.push(option) | ||
@@ -85,3 +92,3 @@ } | ||
const vmMulti = new Vue({ | ||
template: '<multiselect :selected="value" :options="source" @select="onSelect" :multiple="true"></multiselect>', | ||
template: '<multiselect :selected="value" :options="source" @select="onSelect" :multiple="true" id="multi"></multiselect>', | ||
components: { Multiselect }, | ||
@@ -93,3 +100,4 @@ data: { | ||
methods: { | ||
onSelect (option) { | ||
onSelect (option, id) { | ||
calledId = id | ||
eventsLog.push(option) | ||
@@ -102,2 +110,3 @@ } | ||
expect(eventsLog[0]).to.deep.equal('1') | ||
expect(calledId).to.deep.equal('single') | ||
vmSingle.$children[0].select(vmSingle.source[1]) | ||
@@ -108,2 +117,3 @@ expect(eventsLog[1]).to.deep.equal('2') | ||
vmMulti.$children[0].select(vmMulti.source[0]) | ||
expect(calledId).to.deep.equal('multi') | ||
expect(eventsLog[3]).to.deep.equal('1') | ||
@@ -127,7 +137,8 @@ vmMulti.$children[0].select(vmMulti.source[1]) | ||
describe('@remove', () => { | ||
it('should be called after removing an option, passing the removed option', () => { | ||
it('should be called after removing an option, passing the removed option and id', () => { | ||
let eventsLog = [] | ||
let calledId = null | ||
const vmMulti = new Vue({ | ||
template: '<multiselect :selected="value" :options="source" @remove="onRemove" :multiple="true"></multiselect>', | ||
template: '<multiselect :selected="value" :options="source" @remove="onRemove" :multiple="true" :id="1"></multiselect>', | ||
components: { Multiselect }, | ||
@@ -139,4 +150,5 @@ data: { | ||
methods: { | ||
onRemove (option) { | ||
onRemove (option, id) { | ||
eventsLog.push(option) | ||
calledId = id | ||
} | ||
@@ -157,4 +169,71 @@ } | ||
expect(eventsLog.length).to.equal(3) | ||
expect(calledId).to.equal(1) | ||
}) | ||
}) | ||
describe('@close', () => { | ||
it('should be called after closing the dropdown with the current value and id', () => { | ||
let eventsLog = [] | ||
let calledId = null | ||
const vmMulti = new Vue({ | ||
template: '<multiselect :selected="value" :options="source" @close="onClose" :id="1"></multiselect>', | ||
components: { Multiselect }, | ||
data: { | ||
value: [], | ||
source: ['1', '2', '3'] | ||
}, | ||
methods: { | ||
onClose (option, id) { | ||
eventsLog.push(option) | ||
calledId = id | ||
} | ||
} | ||
}).$mount() | ||
vmMulti.$children[0].activate() | ||
vmMulti.$children[0].select(vmMulti.source[1]) | ||
vmMulti.$children[0].select(vmMulti.source[0]) | ||
vmMulti.$children[0].deactivate() | ||
expect(eventsLog[0]).to.deep.equal('2') | ||
vmMulti.$children[0].activate() | ||
vmMulti.$children[0].select(vmMulti.source[2]) | ||
vmMulti.$children[0].deactivate() | ||
expect(eventsLog[1]).to.deep.equal('3') | ||
expect(eventsLog.length).to.equal(2) | ||
expect(calledId).to.equal(1) | ||
}) | ||
}) | ||
describe('@open', () => { | ||
it('should be called after opening the dropdown passing the id', () => { | ||
let idLogs = [] | ||
const vmMulti = new Vue({ | ||
template: '<multiselect :selected="value" :options="source" @open="onOpen" :id="1"></multiselect><multiselect :selected="value" :options="source" @open="onOpen" :id="2"></multiselect>', | ||
components: { Multiselect }, | ||
data: { | ||
value: [], | ||
source: ['1', '2', '3'] | ||
}, | ||
methods: { | ||
onOpen (id) { | ||
idLogs.push(id) | ||
} | ||
} | ||
}).$mount() | ||
vmMulti.$children[0].activate() | ||
vmMulti.$children[1].activate() | ||
vmMulti.$children[0].activate() | ||
vmMulti.$children[1].activate() | ||
expect(idLogs[0]).to.equal(1) | ||
expect(idLogs[1]).to.equal(2) | ||
expect(idLogs.length).to.equal(2) | ||
vmMulti.$children[0].deactivate() | ||
vmMulti.$children[0].activate() | ||
expect(idLogs[2]).to.equal(1) | ||
expect(idLogs.length).to.equal(3) | ||
}) | ||
}) | ||
}) | ||
@@ -771,5 +850,5 @@ | ||
describe('#watch:search', () => { | ||
it('calls onSearchChange(searchQuery) callback when onSearchChange prop is set', (done) => { | ||
it('should call @search-change event callback wheneer search value changes', (done) => { | ||
const vm = new Vue({ | ||
template: '<multiselect :selected="value" :options="source" label="id" key="id" :searchable="true" @search-change="afterSearch" :clear-on-select="false"></multiselect>', | ||
template: '<multiselect :selected="value" :options="source" label="id" key="id" @search-change="afterSearch" :clear-on-select="false"></multiselect>', | ||
components: { Multiselect }, | ||
@@ -852,20 +931,2 @@ data: { | ||
it('should set touched value to true', (done) => { | ||
const vm = new Vue({ | ||
template: '<multiselect :selected="value" :options="source" label="id" key="id" :multiple="true"></multiselect>', | ||
components: { Multiselect }, | ||
data: { | ||
value: [], | ||
source: [{ id: '1' }, { id: '2' }, { id: '3' }] | ||
} | ||
}).$mount() | ||
vm.$children[0].activate() | ||
vm.$children[0].touched = false | ||
vm.$children[0].deactivate() | ||
Vue.nextTick(function () { | ||
expect(vm.$children[0].touched).to.equal(true) | ||
done() | ||
}) | ||
}) | ||
it('should reset search value when multiple == TRUE', (done) => { | ||
@@ -872,0 +933,0 @@ const vm = new Vue({ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
427930
37
3000
1
504