I have created a select form component:
<template>
<div class="col">
<div class="row mb-4">
<label class="col-sm-4 col-form-label col-form-label-sm">{{ label }}</label>
<div class="col-sm-8">
<select
class="form-select form-select-sm"
:class="{'is-invalid': error}"
:disabled="disabled"
:value="modelValue"
@change="updateSelect"
>
<option
v-for="(option, index) in options"
:value="option.id ? option.id : (option.value ? option.value : option)"
:key="option.id ? option.id : index"
>
{{ option.name ? option.name : option }}
</option>
</select>
<div class="invalid-feedback" v-if="error"> {{ error }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "SelectForm",
props: {
label: {
type: String,
default: "",
},
modelValue: {
type: [String, Number, Boolean],
default: "",
},
error: {
type: String,
default: ""
},
disabled: {
type: Boolean,
default: false
},
options: {
type: Object
}
},
setup(props, { emit }) {
const updateSelect = (event) => {
emit("update:modelValue", event.target.value)
}
return {
updateSelect
}
}
}
</script>
<style scoped>
</style>
Options can be for ex:
['Test 1', 'Test 2']
[{id: 1, name: 'Test 1'}]
[{value: 'test1', name: 'Test 1'}]
So in the main component I have this:
<select-form label="Status" :options="userStatuses" v-model="isActive"/>
where userStatuses object is this:
const userStatuses = ref([
{name: 'Active', value: true},
{name: 'Inactive', value: false}
])
The problem is when selecting a value 'Active' it sets the isActive model as "true" (as String - and I need as it is - boolean) and for Inactive => Object (this is what it says in Vue dev tools)
I guess the problem is when returning back the model value
emit("update:modelValue", event.target.value)
I am not sure if I done it correct.
Anyone know how to solve this ?
CodePudding user response:
I have made some changes in updateSelect function and cast the value if it is boolean or number ... and set that value on update:
const updateSelect = (event) => {
let value = event.target.value;
if(value === 'true') { value = true }
if(value === 'false') { value = false }
if(!isNaN(parseInt(value))) { value = parseInt(value) }
emit("update:modelValue", value)
}
CodePudding user response:
This line seems to cause the "Inactive" to return object and "Active" to return a string:
:value="option.id ? option.id : (option.value ? option.value : option)"
Since {name: 'Inactive', value: false}
doesn't have an id
and has a falsy value
it will set the entire option object as value of the option.
You can rewrite it as:
:value="typeof(option) === 'string' ? option : option.id || option.value"
So you'll always get either "true" or "false" in this use-case. However, I believe that the event.target.value
for select will return string either way so you'll need to also change this:
emit("update:modelValue", event.target.value)
to
emit("update:modelValue", event.target.value === "true")