How do I preselect a vue-multiselect option when options is an array of objects?
Solution 1
track-by
usage
The docs indicate that track-by
is "Used to compare objects. Only use if options are objects."
That is, it specifies the object key to use when comparing the object values in options
. The docs should actually state that track-by
is required when the options are objects because <vue-multiselect>
uses track-by
to determine which options in the dropdown are selected and to properly remove a selected option from a multiselect.
Without track-by
, you'd see two buggy behaviors for object-options: (1) the user would be able to re-select already selected options, and (2) attempting to remove selected options would instead cause all options to be re-inserted.
Setting initial values
<vue-multiselect>
doesn't support automatically translating a value array, but you could easily do that from the parent component.
-
Create a local data property to specify
track-by
and initial multiselect values (e.g., namedtrackBy
andinitialValues
, respectively):export default { data() { return { //... trackBy: 'id', initialValues: [2, 5], } } }
-
Bind
<vue-multiselect>.track-by
tothis.trackBy
and<vue-multiselect>.v-model
tothis.value
:<vue-multiselect :track-by="trackBy" v-model="value">
-
Create a watcher on
this.initialValues
that maps those values into an object array based onthis.trackBy
, settingthis.value
to the result:export default { watch: { initialValues: { immediate: true, handler(values) { this.value = this.options.filter(x => values.includes(x[this.trackBy])); } } } }
Vue.component('v-multiselect', window.VueMultiselect.default);
new Vue({
el: '#app',
data () {
return {
trackBy: 'id',
initialValues: [5,2],
value: null,
options: [
{ id: 1, name: 'Vue.js', language: 'JavaScript' },
{ id: 2, name: 'Rails', language: 'Ruby' },
{ id: 3, name: 'Sinatra', language: 'Ruby' },
{ id: 4, name: 'Laravel', language: 'PHP' },
{ id: 5, name: 'Phoenix', language: 'Elixir' }
]
}
},
watch: {
initialValues: {
immediate: true,
handler(values) {
this.value = this.options.filter(x => values.includes(x[this.trackBy]));
}
}
}
})
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script>
<script src="https://unpkg.com/[email protected]"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/vue-multiselect.min.css">
<div id="app">
<v-multiselect :track-by="trackBy"
:options="options"
v-model="value"
label="name"
multiple>
</v-multiselect>
<pre>{{ value }}</pre>
</div>
Solution 2
Looks like a bug. The workaround is to use an actual reference to the object
Vue.component('v-multiselect', window.VueMultiselect.default);
let testOptions=[{id: 1, name: 'Test 1'}, {id: 2, name: 'Test 2'}, {id: 3, name: 'Test 3'}]
new Vue({
el: '#app',
data: function () {
return {
test: testOptions[1], // <- use an object ref here!
testOptions
};
}
});
HartleySan
Updated on June 08, 2022Comments
-
HartleySan about 2 years
I want to pre-select a particular value in a select drop-down generated by
vue-multiselect
.
I can get this to work fine if I have a simple array of strings like the following:['Test 1', 'Test 2', 'Test 3']
However, when I use an array of objects, I can't get this to work. For example, if I have the following:
<v-multiselect :options="[{id: 1, name: 'Test 1'}, {id: 2, name: 'Test 2'}, {id: 3, name: 'Test 3'}]" label="name" track-by="id" v-model="test"> </v-multiselect>
No matter what I set the
test
data property that v-model is connected to, it won't preselect the value. I've tried1
,2
,3
,'1'
,'2'
and'3'
fortest
whentrack-by
isid
and'Test 1'
, etc. whentrack-by
isname
but nothing seems to work.What am I doing wrong here? I looked at the docs at https://vue-multiselect.js.org/#sub-single-select-object, but they don't seem to provide an example when you want to preset a value for an array of objects for the options. Googling has also not returned what I'm looking for.
On a related topic, once I get this working, what would I have to change to select multiple values for when I set the component to
multiple
? Thank you. -
HartleySan over 5 yearsThanks for the reply, Steven. I've tried setting all of the following for
test
in my returneddata
object, and none of them work:1
,'1'
,[1]
,['1']
,{ id: 1 }
,{ id: '1' }
. Any other ideas? Thank you. -
HartleySan over 5 yearsDoesn't seem to make a difference. I set
:options="testOptions"
in the component and then set the following property in thedata
object:[{id: 1, name: 'Test 1'}, {id: 2, name: 'Test 2'}, {id: 3, name: 'Test 3'}]
. Tried settingtest
to all the various possibilities again, but nothing worked. Any other ideas? -
HartleySan over 5 yearsHere ya go: codepen.io/HartleySan/pen/NomLqN?editors=1111. The commented-in code doesn't work, but if you switch that out with the commented out HTML and JS, then it pre-selects the
Test 1
value. Not a clue. -
HartleySan over 5 yearsSteven, you're right, that does work. Not a great workaround though for two reasons: 1) I'm not going to readily have the selected object handy. Usually I'll have the ID, which I wanted to select the object from; and 2) If you do that, you don't even need the
track-by
attribute, in which case, what is that attribute for? Is it buggy? Maybe I'm misunderstanding something, but it seems like the library is buggy. If you settrack-by="id"
, then I would think that you should be able to settest: 1
and be good to go. I wonder if I should submit a bug report on this. -
Steven Spungin over 5 yearsIts surely a bug. I started using
vuetify
after dealing with this kind of stuff... -
HartleySan over 5 yearsThank you for explaining all of that. I get it, and I'm going to have to implement something like that, but honestly, it feels like a poor-man's solution.
vue-multiselect
should automatically handle this for you when you specifytrack-id
.