V-model does not check radio button in custom component

Hi!
I’m having an issue with v-model and checking radio buttons when the radio button is a custom component, a regular html element works fine.
Can anyone figure out what I am missing here…?!

<Lbl v-for="type in shippingTypes" :key="type.Identifier" :customClasses="['freight-option']">
    // Does not set radio button to checked even though value and activeShippingOption have the same values
    <InputRadio
        :value="type.Identifier"
        v-model="activeShippingOption"
        name="freight-component"
        @change="setShipping"
    />
    // The "regular" html element works as expected though the logic is the same
    <input
        :value="type.Identifier"
        v-model="activeShippingOption"
        type="radio"
        name="freight"
        class="input input--radio"
        @change="setShipping"
    >
    <div class="freight-option__description">
        <span class="freight-option__title">{{ type.Name }} - {{ type.Description }}</span>
        <span class="freight-option__delivery-time h-color-grey-darkest">Something something..</span>
    </div>
    <div class="freight-option__price">
        {{ type.Price }} <span class="freight-option__currency">{{ cartData.Currency }}</span>
    </div>
</Lbl>

InputRadio looks like this, and I guess this is where I do something wrong:

<template>
    <input
        :id="id"
        :name="name"
        :required="isRequired"
        :class="customClasses"
        :value="value"
        v-model="localValue"
        type="radio"
        class="input input--radio"
    >
</template>

<script>
export default {
    name: 'InputRadio',
    model: {
        prop: 'selectedButtonValue',
        event: 'change'
    },
    props: {
        // Note: value and selectedButtonValue is used by v-model to calculate if this radio button is active (checked) or not. selectedButtonValue is the value of the selected radio button in the group of radio buttons.
        value: {
            type: [String, Number, Boolean],
            required: true
        },
        selectedButtonValue: {
            type: [String, Number, Boolean],
            required: true
        },
        id: {
            type: String,
            required: false,
            default: null
        },
        name: {
            type: String,
            required: true
        },
        isRequired: {
            type: Boolean,
            required: false,
            default: false
        },
        customClasses: {
            type: Array,
            required: false,
            default () { return [] }
        }
    },
    computed: {
        localValue: {
            get () {
                return this.value
            },
            set () {
                this.$emit('change', event.target.value)
            }
        }
    }
}
</script>

So, after a much needed weekend my mind cleared up and I managed to solve this by simply figuring out that I bound wrong props to v-model and such misstakes.

I don’t have the time right now to explain the code but here’s the related parts of my components:

Checkout:

<FreightOption
    v-for="type in shippingTypes"
    :key="type.Identifier"
    :option="type"
    :activeShippingOption="activeShippingOption"
    v-model="activeShippingOption"
/>



data () {
    return { activeShippingOption = '' } // This value is set when the component is created
}

FreightOption:

<InputRadio
    :selectedButtonValue="activeShippingOption"
    :value="option.Identifier"
    v-model="localActiveShippingOption"
    name="freight"
/>



model: {
    prop: 'activeShippingOption',
    event: 'change'
},
props: {
    option: {
        type: Object,
        required: true
    },
    activeShippingOption: {
        type: String,
        required: false,
        default: null
    }
},
computed: {
    localActiveShippingOption: {
        get () {
            return this.activeShippingOption
        },
        set () {
            this.$emit('change', event.target.value)
        }
    }
}

InputRadio:

<input
    :id="id"
    :name="name"
    :required="isRequired"
    :class="customClasses"
    :value="value"
    v-model="localSelectedButtonValue"
    type="radio"
    class="input input--radio"
>



model: {
    prop: 'selectedButtonValue',
    event: 'change'
},
props: {
        value: {
            type: [String, Number, Boolean],
            required: true
        },
        selectedButtonValue: {
            type: [String, Number, Boolean],
            required: true
        }
},
computed: {
    localSelectedButtonValue: {
        get () {
            return this.selectedButtonValue
        },
        set () {
            this.$emit('change', event.target.value)
        }
    }
}
1 Like

This saved my life! Thank you for posting your code!

Anyone who has never heard about the model: {} config object may look it up here:

1 Like