<template>
<label v-if="label">{{ label }}</label>
<select
class="field"
:value="modelValue"
v-bind="{
...$attrs,
onChange: ($event) => { $emit('update:modelValue', $event.target.value) }
}"
>
<option
v-for="option in options"
:value="option"
:key="option"
:selected="option === modelValue"
>{{ option }}</option>
</select>
</template>
<script>
export default {
props: {
label: {
type: String,
default: ''
},
modelValue: {
type: [String, Number],
default: ''
},
options: {
type: Array,
required: true
}
}
}
</script>
Rewrite in Composeable API
<template>
<label v-if="label">{{ label }}</label>
<select
class="field"
v-model="modelValue"
v-bind="$attrs"
>
<option
v-for="option in options"
:value="option"
:key="option"
>
{{ option }}
</option>
</select>
</template>
<script setup>
import { defineProps, defineModel } from 'vue';
// Define static props
const { label, options } = defineProps({
label: {
type: String,
default: ''
},
options: {
type: Array,
required: true
}
});
// Define modelValue using defineModel for two-way binding
const modelValue = defineModel({
type: [String, Number],
default: ''
});
</script>
Usage from parent component:
<template>
<CustomSelect
v-model="selectedOption"
:options="['Option 1', 'Option 2', 'Option 3']"
label="Choose an option:"
/>
</template>
<script setup>
import { ref } from 'vue';
import CustomSelect from './CustomSelect.vue';
const selectedOption = ref('');
</script>