Skip to content

Commit d2e12ef

Browse files
author
Damian Dulisz
committed
Groups slightly refactored and tests
1 parent c5a3e91 commit d2e12ef

File tree

7 files changed

+230
-61
lines changed

7 files changed

+230
-61
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Probably the most complete *selecting* solution for Vue.js 2.0, without jQuery.
2323
* Support for `v-model`
2424
* `@update` has changed to `@input` to also work with v-model
2525
* `:selected` has changed to `:value` for the same reason
26+
* Browserify users: if you wish to import `.vue` files, please add `vueify` transform.
2627

2728
## Install & basic usage
2829

docs/main.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,25 @@ new Vue({
4040
},
4141
{
4242
groupLabel: 'grupa 2',
43-
values: ['2', '2a', '2b', 'bc', 'aa', 'ee2', 'ee3']
43+
values: ['2', '2a', '2b', 'bcc', 'aa', 'ee2', 'ee33']
44+
}
45+
],
46+
groups2: [
47+
{
48+
groupLabel: 'grupa 1',
49+
values: [
50+
{ label: 'aa1', id: '1' },
51+
{ label: 'aa2', id: '2' },
52+
{ label: 'ab', id: '3' }
53+
]
54+
},
55+
{
56+
groupLabel: 'grupa 2',
57+
values: [
58+
{ label: 'bb1', id: '4' },
59+
{ label: 'bb2', id: '5' },
60+
{ label: 'ab', id: '6' }
61+
]
4462
}
4563
],
4664
groupsSelected: [],

docs/partials/examples/_groups.jade

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ p.typo__p
66
label.typo__label Groups
77
multiselect(
88
v-model="groupsSelected",
9-
:options="groups",
9+
:options="groups2",
1010
:multiple="true",
1111
:searchable="true",
12+
:close-on-select="false",
1213
group-key="values",
13-
placeholder="Type to search"
14+
group-label="groupLabel",
15+
placeholder="Type to search",
16+
track-by="id",
17+
label="label",
1418
)
1519
span(slot="noResult").
1620
Oops! No elements found. Consider changing the search query.

package.json

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,6 @@
2424
"lint": "eslint --ext .js,.vue src test/unit/specs",
2525
"bundle": "webpack --config build/webpack.bundle.conf.js"
2626
},
27-
"browserify": {
28-
"transform": [
29-
"vueify",
30-
[
31-
"babelify",
32-
{
33-
"presets": [
34-
"es2015"
35-
]
36-
}
37-
]
38-
]
39-
},
4027
"devDependencies": {
4128
"babel-core": "^6.7.7",
4229
"babel-helper-vue-jsx-merge-props": "^2.0.1",
@@ -91,10 +78,10 @@
9178
"sinon": "^1.17.3",
9279
"sinon-chai": "^2.8.0",
9380
"url-loader": "^0.5.7",
94-
"vue": "^2.0.0-rc.6",
81+
"vue": "^2.0.0",
9582
"vue-hot-reload-api": "^1.2.0",
9683
"vue-html-loader": "^1.0.0",
97-
"vue-loader": "^9.3.2",
84+
"vue-loader": "^9.7.0",
9885
"vue-style-loader": "^1.0.0",
9986
"webpack": "^1.13.0",
10087
"webpack-dev-middleware": "^1.4.0",

src/Multiselect.vue

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@
5050
@keydown.tab.stop.prevent.self="addPointerElement()"
5151
@keydown.delete="removeLastElement()"
5252
class="multiselect__input"/>
53-
<span
54-
v-if="!searchable && !multiple"
55-
class="multiselect__single"
56-
v-text="currentOptionLabel || placeholder">
57-
</span>
53+
<span
54+
v-if="!searchable"
55+
class="multiselect__single"
56+
v-text="currentOptionLabel || placeholder">
57+
</span>
5858
</div>
5959
<transition name="multiselect">
6060
<ul
@@ -72,7 +72,7 @@
7272
<li v-for="(option, index) of filteredOptions" :key="index">
7373
<span
7474
tabindex="0"
75-
v-if="!option.isLabel"
75+
v-if="!option.$isLabel"
7676
:class="optionHighlight(index, option)"
7777
@mousedown.prevent="select(option)"
7878
@mouseenter="pointerSet(index)"
@@ -87,10 +87,10 @@
8787
</multiselect-option>
8888
</span>
8989
<span
90-
v-if="option.isLabel"
90+
v-if="option.$isLabel"
9191
:class="optionHighlight(index, option)"
9292
class="multiselect__option multiselect__option--disabled">
93-
{{ option.label }}
93+
{{ option.$groupLabel }}
9494
</span>
9595
</li>
9696
</template>
@@ -336,7 +336,8 @@ fieldset[disabled] .multiselect {
336336
margin-bottom: 8px;
337337
}
338338
339-
.multiselect__tag ~ .multiselect__input {
339+
.multiselect__tag ~ .multiselect__input,
340+
.multiselect__tag ~ .multiselect__single {
340341
width: auto;
341342
}
342343

src/multiselectMixin.js

Lines changed: 52 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,40 @@ function filterOptions (options, search, label) {
1212
: options.filter(option => includes(option, search))
1313
}
1414

15+
function stripGroups (options) {
16+
return options.filter(option => !option.$isLabel)
17+
}
18+
19+
function flattenOptions (values, label) {
20+
return (options) =>
21+
options.reduce((prev, curr) => {
22+
if (curr[values] && curr[values].length) {
23+
prev.push({
24+
$groupLabel: curr[label],
25+
$isLabel: true
26+
})
27+
return prev.concat(curr[values])
28+
}
29+
return prev.concat(curr)
30+
}, [])
31+
}
32+
33+
function filterGroups (search, label, values, groupLabel) {
34+
return (groups) =>
35+
groups.map(group => {
36+
const groupOptions = filterOptions(group[values], search, label)
37+
38+
return groupOptions.length
39+
? {
40+
[groupLabel]: group[groupLabel],
41+
[values]: groupOptions
42+
}
43+
: []
44+
})
45+
}
46+
47+
const flow = (...fns) => x => fns.reduce((v, f) => f(v), x)
48+
1549
module.exports = {
1650
data () {
1751
return {
@@ -206,6 +240,9 @@ module.exports = {
206240
},
207241
groupKey: {
208242
type: String
243+
},
244+
groupLabel: {
245+
type: String
209246
}
210247
},
211248
created () {
@@ -219,7 +256,7 @@ module.exports = {
219256

220257
if (this.localSearch) {
221258
options = this.groupKey
222-
? this.filterAndFlat(options)
259+
? this.filterAndFlat(options, search, this.label)
223260
: filterOptions(options, search, this.label)
224261

225262
options = this.hideSelected
@@ -243,12 +280,13 @@ module.exports = {
243280
}
244281
},
245282
optionKeys () {
283+
const options = this.groupKey ? this.flatAndStrip(this.options) : this.options
246284
return this.label
247-
? this.options.map(element => element[this.label].toString().toLowerCase())
248-
: this.options.map(element => element.toString().toLowerCase())
285+
? options.map(element => element[this.label].toString().toLowerCase())
286+
: options.map(element => element.toString().toLowerCase())
249287
},
250288
currentOptionLabel () {
251-
return this.getOptionLabel(this.internalValue)
289+
return this.getOptionLabel(this.internalValue) + ''
252290
}
253291
},
254292
watch: {
@@ -271,30 +309,16 @@ module.exports = {
271309
},
272310
methods: {
273311
filterAndFlat (options) {
274-
return this.flattenOptions(
275-
this.filterGroups(options)
276-
)
312+
return flow(
313+
filterGroups(this.search, this.label, this.groupKey, this.groupLabel),
314+
flattenOptions(this.groupKey, this.groupLabel)
315+
)(options)
277316
},
278-
filterGroups (groups) {
279-
return groups.map(group => {
280-
const groupOptions = filterOptions(group[this.groupKey], this.search, this.label)
281-
282-
return groupOptions.length
283-
? { groupLabel: group.groupLabel, groupOptions }
284-
: []
285-
})
286-
},
287-
flattenOptions (options) {
288-
return options.reduce((prev, curr) => {
289-
if (curr.groupOptions && curr.groupOptions.length) {
290-
prev.push({
291-
label: curr.groupLabel,
292-
isLabel: true
293-
})
294-
return prev.concat(curr.groupOptions)
295-
}
296-
return prev.concat(curr)
297-
}, [])
317+
flatAndStrip (options) {
318+
return flow(
319+
flattenOptions(this.groupKey, this.groupLabel),
320+
stripGroups
321+
)(options)
298322
},
299323
updateSearch (query) {
300324
this.search = query.trim().toLowerCase().toString()
@@ -349,7 +373,7 @@ module.exports = {
349373
getOptionLabel (option) {
350374
if (!option && option !== 0) return ''
351375
if (option.isTag) return option.label
352-
return this.customLabel(option, this.label) + ''
376+
return this.customLabel(option, this.label) || ''
353377
},
354378
/**
355379
* Add the given option to the list of selected options

0 commit comments

Comments
 (0)