Search code examples
vue.jsvue-componentradio-group

How do I keep two identical Vue components in sync with each other?


I'm trying to make two radio button clusters on the same page (but inside different drawers) keep in sync with each other. This worked before I broke them out into a component.

Now my component looks like:

Vue.component('radio-cluster', {
props: ['value'],
template: `
    ...
    <input type="radio" name="radio" value="Hour" :checked="value == 'Hour'" @input="$emit('input', $event.target.value)">
    <input type="radio" name="radio" value="Week" :checked="value == 'Week'" @input="$emit('input', $event.target.value)">
    ...
    `,
});

The Vue instance:

new Vue({
el: '#app',
data: function () {
    return {
        timePeriod: "Hour"
    }
});

And the relevant HTML:

<div id="app">
    <radio-cluster v-model="timePeriod"></radio-cluster>
    ...
    <radio-cluster v-model="timePeriod"></radio-cluster>
</div>

The behavior I'm getting is odd. It will correctly show in one of the two clusters, and emit the correct event from either one. But the other component ignores the event from the one I clicked on. How can I make Vue take the value updated in one component and automatically give it to the other every time either one updates?


Solution

  • Seems like the cause of you problem is the same name for each input.

    From documentation
    A radio group is defined by giving each of radio buttons in the group the same name. Once a radio group is established, selecting any radio button in that group automatically deselects any currently-selected radio button in the same group.

    Try to remove name attribute:

    <input type="radio" value="Hour" :checked="value == 'Hour'" @input="$emit('input', $event.target.value)">
    <input type="radio" value="Week" :checked="value == 'Week'" @input="$emit('input', $event.target.value)">
    

    if name attribute is required use different names for each component.
    Thanks @Ferrybig for the comment.