Search code examples
vue.jsvue-componentvuex

How to display many times the same component with vuex link inside


I'm new to Vue and Vuex. I made a component with radio button, and this component is two-way bind with the store.

Now that the component is working, i would like to use it for multiple item by calling it several time, and indicates to it which item of the vuex store it should be bound to. In this way, i'll be able to loop of the array containing all item on which apply the radio button modification.

In my store, I have this array :

state { 
    [...other data...]
    arrayX { 
       item1: { name : 'a', value : 'nok'}
       item2: { name : 'b', value : 'ok}},
    [...other data...]

This array is bind with v-model inside the component :

<template>
    <div class="radio">
            <input type="radio" name="a" value="nok" v-model="arrayX.item1.value" id="nok"/>
            <label for="nok"> Nok </label>
          </div>
          <div class="radio">
            <input type="radio" name="a" value=""  v-model="arrayX.item1.value" id="empty"/>
            <label for="empty">None</label>
          </div>
          <div class="radio">
            <input type="radio" name="a" value="ok_but" v-model="arrayX.item1.value" id="ok_but"/>
            <label for="ok_but">Ok but</label>
          </div>
          <div class="radio">
            <input type="radio" name="a" value="ok" v-model="arrayX.item1.value" id="ok"/>
            <label for="ok">Ok</label>
          </div>
        </div>   

    </template>


<script>
import { mapFields } from 'vuex-map-fields';
  export default {
    name: 'SwitchColors',
    computed:{
      ...mapFields(['arrayX' ])
    }
  }
</script>

Solution

  • I created an example scenario in my Vue 2 CLI sandbox app. Each radio button component is bound to the Vuex store array element through a computed property. I pass the store array index value as a prop from the parent to the radio component.

    RadioButtonVuex.vue

    <template>
      <div class="radio-button-vuex">
        <hr>
        <div class="row">
          <div class="col-md-6">
            <input type="radio" value="One" v-model="picked">
            <label>One</label>
            <br>
            <input type="radio" value="Two" v-model="picked">
            <label>Two</label>
          </div>
        </div>
      </div>
    </template>
    
    <script>
      export default {
        props: {
          pickedIndex: {
            type: Number,
            required: true
          }
        },
        computed: {
          picked: {
            get() {
              return this.$store.state.radioSelections[this.pickedIndex].picked;
            },
            set(newValue) {
              this.$store.commit('updateSelection', { index: this.pickedIndex, newValue: newValue });
            }
          }
        },
      }
    </script>
    
    <style scoped>
      label {
        margin-left: 0.5rem;
      }
    </style>
    

    Parent.vue

    <template>
      <div class="parent">
        <h3>Parent.vue</h3>
        <radio-button-vuex :pickedIndex="0" />
        <radio-button-vuex :pickedIndex="1" />
      </div>
    </template>
    
    <script>
      import RadioButtonVuex from './RadioButtonVuex.vue'
    
      export default {
        components: {
          RadioButtonVuex
        }
      }
    </script>
    

    store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex);
    
    export default new Vuex.Store({
      state: {
        radioSelections: [
          {
            picked: 'One'
          },
          {
            picked: 'Two'
          }
        ]
      },
      mutations: {
        updateSelection(state, payload) {
          state.radioSelections[payload.index].picked = payload.newValue;
        }
      }
    })