Thore
Thore

Reputation: 1838

Vue 3 two way binding with select box

I'm trying to create a two way binding between my parent (create user form) and a child component (reusable selectbox).

The parent component

<template>
    <Selectbox :selectedOption="selectedRole" :options="roles" />
    <span>SelectedRole: {{ selectedRole }}</span>
</template>

<script>
    import Selectbox from '@/components/formElements/Selectbox.vue';

    export default {
        components: {
            Selectbox,
        },
        async created() {
            await this.$store.dispatch('roles/fetchRoles');
            this.selectedRole = this.roles[0].value;
        },
        data() {
            return {
                selectedRole: null,
            };
        },
        computed: {
            roles() {
                return this.$store.getters['roles/roles'].map((role) => ({
                    value: role.id.toString(),
                    label: role.name,
                }));
            },
        },
    };
</script>

I'm passing down the roles as options and the selectedRole variable as selectedOption.

The child component

<template>
    <select :value="selectedOption" @input="(event) => $emit('update:selectedOption', event.target.value)">
        <option v-for="option in options" :value="option.value" :key="option.value">{{ option.label }}</option>
    </select>
</template>

<script>
    export default {
        props: {
            options: {
                type: Array,
                required: true,
            },
            selectedOption: {
                type: String,
                required: false,
            },
        },
    };
</script>

The selectedOption is assigned to the value together. When another value is selected I want to update the passed down value in the parent component. Therefore I'm using an $emit function but that's not working right now.

I also tried to use v-model to combine the value and change attributes but without success.

<select v-model="selectedOption">

What's the correct way?

Code: Codesandbox

Upvotes: 1

Views: 1865

Answers (1)

tho-masn
tho-masn

Reputation: 1174

I guess this is the handling you want to achieve: https://codesandbox.io/s/practical-orla-i8n3t?file=/src/components/Selectbox.vue

If you use v-model on a sub-component, you have to handle it properly in the sub-component.

<custom-select v-model="value" />

<!-- IS THE SAME AS -->

<custom-select
   :modelValue="value"
   @update:modelValue="value = $event"
/>

So if you use v-model, a property with the name modelValue gets passed down to the sub-component. If the modelValue changes (which means another option in the select list gets selected) you have to emit a change event, indicating that the modelValue got changed: $emit('update:modelValue'). v-model automatically updates it's value if this event occurs.

Source: https://learnvue.co/2021/01/everything-you-need-to-know-about-vue-v-model/

Upvotes: 5

Related Questions