Skip to content

Commit 3e631fd

Browse files
author
Damian Dulisz
committed
Support for custom option templates using partials
1 parent a1473dc commit 3e631fd

19 files changed

+247
-26
lines changed

README.md

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
# vue-multiselect ![Build Status](https://circleci.com/gh/monterail/vue-multiselect/tree/master.svg?style=shield&circle-token=5c931ff28fd12587610f835472becdd514d09cef)
22
Probably the most complete *selecting* solution for Vue.js, without jQuery.
33

4+
#### Current version: v1.1.0
5+
46
### Features & characteristics:
57
* NO dependencies
68
* Single select
79
* Multiple select
810
* Tagging
11+
* Custom option templates (1.1.0+)
912
* Dropdowns
1013
* Filtering
1114
* Search with suggestions
@@ -74,7 +77,6 @@ export default {
7477
## Roadmap:
7578

7679
* Grouping
77-
* Support for partials
7880
* Examples of custom components / templates ready to use in project
7981

8082
## Examples
@@ -110,7 +112,7 @@ multiselect(
110112
```
111113

112114
### Multiple select with search
113-
``` jade
115+
```jade
114116
multiselect(
115117
:options="source",
116118
:selected="multiValue",
@@ -125,7 +127,7 @@ multiselect(
125127

126128
### Tagging
127129
with `@tag` event
128-
``` jade
130+
```jade
129131
multiselect(
130132
:options="taggingOptions",
131133
:selected="taggingSelected",
@@ -140,8 +142,7 @@ multiselect(
140142
)
141143
```
142144

143-
``` javascript
144-
145+
```javascript
145146
addTag (newTag) {
146147
const tag = {
147148
name: newTag,
@@ -152,6 +153,50 @@ addTag (newTag) {
152153
},
153154
```
154155

156+
### Custom option template
157+
Using partial API
158+
```jade
159+
multiselect(
160+
:options="styleList",
161+
:selected="selectedStyle",
162+
:option-height="130",
163+
:custom-label="styleLabel",
164+
@update="updateSelectedStyle",
165+
option-partial="customOptionPartial"
166+
placeholder="Fav No Man’s Sky path"
167+
label="title"
168+
key="title"
169+
)
170+
```
171+
172+
``` javascript
173+
import customOptionPartial from './partials/customOptionPartial.html'
174+
Vue.partial('customOptionPartial', customOptionPartial)
175+
176+
// ...Inside Vue component
177+
methods: {
178+
styleLabel ({ title, desc }) {
179+
return `${title}${desc}`
180+
},
181+
updateSelectedStyle (style) {
182+
this.selectedStyle = style
183+
}
184+
}
185+
```
186+
187+
``` html
188+
<div>
189+
<img class="option__image" :src="option.img" alt="No Man’s Sky" />
190+
<div class="option__desc">
191+
<span class="option__title">{{ option.title }}</span>
192+
<span class="option__small">
193+
{{ option.desc }}
194+
</span>
195+
</div>
196+
</div>
197+
198+
```
199+
155200
### Asynchronous dropdown
156201
``` jade
157202
multiselect(
@@ -168,7 +213,7 @@ multiselect(
168213
Oops! No elements found. Consider changing the search query.
169214
```
170215

171-
``` javascript
216+
```javascript
172217
methods: {
173218
asyncFind (query) {
174219
this.countries = findService(query)

docs/assets/base/_typo.sass

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,5 @@ kbd
191191
padding: 3px 5px
192192
border-radius: 4px
193193
background: $tertiary-color
194+
font-weight: 300
195+
font-size: rem(16px)

docs/docs.scss

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,30 @@ body {
107107
color: $secondary-color;
108108
transform: translateX(-100%);
109109
}
110+
111+
.option__image {
112+
max-height: 100px;
113+
display: inline-block;
114+
vertical-align: middle;
115+
}
116+
117+
.option__desc {
118+
display: inline-block;
119+
vertical-align: middle;
120+
padding: rem(10px);
121+
}
122+
123+
.option__title {
124+
font-size: rem(24px);
125+
}
126+
127+
.option__small {
128+
margin-top: rem(10px);
129+
display: block;
130+
}
131+
132+
.version--changed {
133+
margin-right: rem(10px);
134+
font-size: rem(20px);
135+
color: $primary-color;
136+
}

docs/index.jade

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ html(lang="en")
4444
hr.typo__hr
4545
include ./partials/examples/_tagging
4646

47+
hr.typo__hr
48+
include ./partials/examples/_partials
49+
4750
hr.typo__hr
4851
include ./partials/examples/_action
4952

docs/main.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import Vue from 'vue'
22

33
import Multiselect from '../src/Multiselect'
44
import countries from './data/countries.json'
5+
import customOptionPartial from './partials/customOptionPartial.html'
6+
7+
Vue.partial('customOptionPartial', customOptionPartial)
58

69
function throttle (callback, limit) {
710
var wait = false
@@ -54,7 +57,14 @@ new Vue({
5457
isLoading: false,
5558
isNavSticky: false,
5659
firstColor: Math.floor(Math.random() * 255),
57-
secondColor: Math.floor(Math.random() * 255)
60+
secondColor: Math.floor(Math.random() * 255),
61+
styleList: [
62+
{ title: 'Space Pirate', desc: 'More space battles!', img: '/static/posters/fleet.png' },
63+
{ title: 'Merchant', desc: 'PROFIT!', img: '/static/posters/trading_post.png' },
64+
{ title: 'Explorer', desc: 'Discovering new species!', img: '/static/posters/creatures.png' },
65+
{ title: 'Miner', desc: 'We need to go deeper!', img: '/static/posters/resource_lab.png' }
66+
],
67+
selectedStyle: { title: 'Explorer', desc: 'Discovering new species!', img: '/static/posters/creatures.png' }
5868
}
5969
},
6070
computed: {
@@ -138,9 +148,15 @@ new Vue({
138148
console.log('@update: ', value)
139149
this.valuePrimitive = value
140150
},
151+
updateSelectedStyle (style) {
152+
this.selectedStyle = style
153+
},
141154
nameWithLang ({ name, language }) {
142155
return `${name} — [${language}]`
143156
},
157+
styleLabel ({ title, desc }) {
158+
return `${title}${desc}`
159+
},
144160
onSelect (option) {
145161
console.log('@select: ', option)
146162
},

docs/partials/_nav.jade

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ ul.list(
1515
+nav-element('Multiselect with search', 'multiselect-search')
1616
+nav-element('Asynchronous select', 'ajax')
1717
+nav-element('Tagging', 'tagging')
18+
+nav-element('Custom option templates', 'partials')
1819
+nav-element('Action select', 'action')
1920
+nav-element('Custom configuration', 'custom')
2021

docs/partials/_start.jade

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ section.start(
55
h1.typo__h1
66
img.logo(src="./static/vue-logo.png")
77
| Vue-multiselect
8-
small.version (v1.0.1)
8+
small.version (v1.1.0)
99
h3.typo__h3 The most complete selecting solution for
1010
= ' '
1111
a.typo__link(href="http://vuejs.org" target="_BLANK") Vue.js
@@ -32,9 +32,9 @@ section.start(
3232
.grid__column.grid__unit--md-6.list
3333
ul.list__ul
3434
li.typo__li Single / multi select
35-
li.typo__li Dropdowns
3635
li.typo__li: a.typo__link(href="#search") Searchable
3736
li.typo__li: a.typo__link(href="#tagging") Tagging
37+
li.typo__li: a.typo__link(href="#partials") Custom option templates (1.1.0+)
3838
li.typo__li: a.typo__link(href="#action") Action dispatcher
3939
.grid__column.grid__unit--md-6.list
4040
ul.list__ul

docs/partials/api/_props.jade

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,12 @@ h2.typo__h2#props Props
183183
td.table__td: kbd false
184184
td.table__td
185185
| Enable/disable the multiselect.
186+
tr.table__tr
187+
td.table__td: strong OptionPartial
188+
td.table__td String
189+
td.table__td: kbd multiselectBasicOptionPartial
190+
td.table__td
191+
| Name of the registered custom option partial.
186192

187193
tr.table__tr
188194
td.table__td.utils--center(colspan="4"): strong pointerMixin.js
@@ -193,3 +199,9 @@ h2.typo__h2#props Props
193199
td.table__td: kbd true
194200
td.table__td
195201
| Enable/disable highlighting of the pointed value.
202+
tr.table__tr
203+
td.table__td: strong OptionHeight
204+
td.table__td Number
205+
td.table__td: kbd 40
206+
td.table__td
207+
| Set the height of the option. Used for scroll calculations.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<div>
2+
<img class="option__image" :src="option.img" alt="No Man’s Sky" />
3+
<div class="option__desc">
4+
<span class="option__title">{{ option.title }}</span>
5+
<span class="option__small">
6+
{{ option.desc }}
7+
</span>
8+
</div>
9+
</div>

docs/partials/examples/_partials.jade

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
h2.typo__h2#partials
2+
small.version--changed v1.1.0+
3+
| Custom option templates
4+
p.typo__p
5+
| You can provide the name of a registered custom partial to use as a template for elements in the option list.
6+
p.typo__p
7+
| If no partial is provided it will use the default one: <kbd>&lt;span v-text="getOptionLabel(option)"&gt;&lt;/span&gt;</kbd>
8+
p.typo__p
9+
| To ensure the keyboard navigation works properly, remember to set the <kbd>:option-height</kbd> to equal the height of the option template. By default, the component assumes an option height of 40px.
10+
.grid__row
11+
.grid__column.grid__unit--md-5
12+
label.typo__label Fav No Man’s Sky path
13+
multiselect(
14+
:options="styleList",
15+
:selected="selectedStyle",
16+
:option-height="130",
17+
:custom-label="styleLabel",
18+
@update="updateSelectedStyle",
19+
option-partial="customOptionPartial"
20+
placeholder="Fav No Man’s Sky path"
21+
label="title"
22+
key="title"
23+
)
24+
pre.language-json
25+
code.
26+
{{ selectedStyle | json }}
27+
28+
.grid__column.grid__unit--md-7
29+
label.typo__label Code sample
30+
pre.language-jade
31+
code.
32+
multiselect(
33+
:options="styleList",
34+
:selected="selectedStyle",
35+
:option-height="130",
36+
:custom-label="styleLabel",
37+
@update="updateSelectedStyle",
38+
option-partial="customOptionPartial"
39+
placeholder="Fav No Man’s Sky path"
40+
label="title"
41+
key="title"
42+
)
43+
44+
pre.language-javascript
45+
code.
46+
import customOptionPartial from './partials/customOptionPartial.html'
47+
Vue.partial('customOptionPartial', customOptionPartial)
48+
49+
// ...Inside Vue component
50+
methods: {
51+
styleLabel ({ title, desc }) {
52+
return `${title} – ${desc}`
53+
},
54+
updateSelectedStyle (style) {
55+
this.selectedStyle = style
56+
}
57+
}
58+
59+
pre.language-html
60+
code.
61+
&lt;!-- customOptionPartial.html --&gt;
62+
&lt;div&gt;
63+
&lt;img class="option__image" :src="option.img" alt="Poster" /&gt;
64+
&lt;div class="option__desc"&gt;
65+
&lt;span class="option__title"&gt;{&zwnj;{ option.title }}&lt;/span&gt;
66+
&lt;span class="option__small"&gt;
67+
{&zwnj;{ option.desc }}
68+
&lt;/span&gt;
69+
&lt;/div&gt;
70+
&lt;/div&gt;

0 commit comments

Comments
 (0)