Reputation: 95
I'm trying to create a reusable Select component that will work with any Array passed to it as options.
I have it working if the Object properties in the array share the same names bound in the component, but if you pass an array of objects that have different property/attribute names, as expected, the options will not render. How can I assign on the component which object property I want as the option value and which I want as the option label/name?
FormSelect.vue / Component
<template>
<select :id="id" v-model="selected">
<option v-if="options.length > 0" value="">Please Select</option>
<option
v-if="options.length > 0"
v-for="(option, index) in options"
:key="index"
:selected="selected"
:value="option.value"
v-text="option.name"
/>
</select>
</template>
<script>
props: {
value: {
type: [Array, String, Number, Object],
default: null
},
options: {
type: Array,
default: () => []
}
},
computed: {
selected: {
get() {
return this.value ? this.value : "";
},
set(v) {
this.$emit("input", v);
}
}
}
</script>
Parent.vue / Parent
<form-select
id="gender"
label="Gender"
:options="genderOptions"
@input="handleEdit(deep(profile))"
v-model="user.gender"
/>
This works:
genderOptions: [
{ name: "Male", value: "MALE" },
{ name: "Female", value: "FEMALE" }
],
This would not (notice obj key names):
genderOptions: [
{ id: "Male", gender: "MALE" },
{ id: "Female", gender: "FEMALE" }
],
So I'm thinking there needs to be a way to tell the component which properties I want to use as the option value and label. Something like this, but then it would also need to be handles on the component side:
<form-select
id="gender"
label="Gender"
:options="genderOptions"
optionVal="gender"
optionName="id"
@input="handleEdit(deep(profile))"
v-model="user.gender"
/>
Upvotes: 1
Views: 877
Reputation: 1
You're missing to add optionVal
and optionName
props to your component and to work with them, i suggest the following solution
<script>
props: {
value: {
type: [Array, String, Number, Object],
default: null
},
options: {
type: Array,
default: () => []
},
optionVal:{
type:String,
default: 'value'
},
optionName:{
type:String,
default: 'name'
}
},
computed: {
selected: {
get() {
return this.value ? this.value : "";
},
set(v) {
this.$emit("input", v);
}
}
}
</script>
<select :id="id" v-model="selected">
<option v-if="options.length > 0" value="">Please Select</option>
<option
v-if="options.length > 0"
v-for="(option, index) in options"
:key="index"
:selected="selected"
:value="option[optionVal]"
v-text="option[optionName]"
/>
</select>
Upvotes: 1