[Vuejs]-Clicking radio button selects radio in all groups in Bootstrap-Vue

0👍

The issue you’re running into is with how you’re using v-model on the b-form-group-component:

<b-form-radio-group
  v-model="question_option"
  :options="item.qOptions"
  :name="index.toString()"
  stacked
/>

You’re displaying one radio group per item, but then storing the results from all of those groups in the same, single data variable: question_option.

In order to fix this, you’ll need to store the selected options in an array, so you can keep track of the selection for each question individually. You can either create a new array for it, or add a property to the item objects stored in dataList to use, whichever makes more sense to you.

In the example below, I made the following changes:

  • I added a question_option property to each item in dataList
  • Changed v-model="question_option" to v-model="item.question_option"
  • Changed the "hint" to reference item.question_option too
  • Added a span below "hint" to show the selection for the given question, just as an example to show that they’re storing properly

Example

new Vue({
  el: '#app',
  data() { return {
    dataList: [
      {
        question: 'The first question',
        qOptions: [ { text: 'Option 1', value: 1 },
          { text: 'Option 2', value: 2 },
          { text: 'Option 3', value: 3 },
          { text: 'Option 4', value: 4 }],
        hints: 'First question hint',
        question_option: '', // New option property for selection storage
      },
      {
        question: 'The second question',
        qOptions: [ { text: 'Option 1', value: 1 },
          { text: 'Option 2', value: 2 },
          { text: 'Option 3', value: 3 },
          { text: 'Option 4', value: 4 }],
        hints: 'Second question hint',
        question_option: '', // New option property for selection storage
      },
    ],
  }},
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap@4/dist/css/bootstrap.min.css" /><link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.css" /><script src="//unpkg.com/vue@latest/dist/vue.min.js"></script><script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.min.js"></script>

<div id="app">
  <ul class="question_list" v-for="(item, index) in dataList" :key="index">
    <li>
      <p><b>{{ index + 1 + '. ' + item.question }}</b></p>
      <b-form-group :id="index.toString()" :name="index.toString()">
        <!-- Replace "question_option" with "item.question_option" -->
        <b-form-radio-group
          v-model="item.question_option"
          :options="item.qOptions"
          :name="index.toString()"
          stacked
        />
      </b-form-group>
      <b-card-text class="mt-1 mb-0">
        <!-- Replace "question_option" with "item.question_option" -->
        <p><b>Hints:</b> <span v-if="item.question_option !== ''" v-html="item.hints"></span></p>
      </b-card-text>
      <!-- Added a span to show selection, for clarity -->
      <b-card-text class="mt-1 mb-0">
        <p><b>Selected:</b> <span>{{ item.question_option }}</span></p>
      </b-card-text>
    </li>
  </ul>
</div>

0👍

At first, you have re-assign the data Object by mapping. here is the code

dataFormatedList (data, userReviewList) {
return data.map(item => {
    // Options
    const mySplitP = item.options.split('<p>')
    const mySplitPClose = mySplitP[1].split('</p>')[0]
    const mySplitSlash = mySplitPClose.split('///')
    const correctAnsIndex = mySplitSlash.findIndex(element => element.includes("@@"))
    const mySplitAtTheRate = mySplitSlash[correctAnsIndex].split('@@')[1]
    mySplitSlash.splice(correctAnsIndex, 1, mySplitAtTheRate)
    // Question
    const questionSplit = item.question.split('</p>')[0]
    const question = questionSplit.split('<p>')[1]

    const myOption = mySplitSlash.map((item, index) => {
        const is_correct = index === correctAnsIndex ? true : false
        const qOptions = {
        text: item,
        value: index,
        is_correct: is_correct,
        bg_color: 'radio_option_default_custom_design',
        text_color: 'text-primary',
        }
        return Object.assign({}, qOptions)
    })
    const questionOptions = {
        qOptions: myOption,
        question: question,
        correctAnsIndex: correctAnsIndex
    }
    return Object.assign({}, item, questionOptions)
})

}

for looping here

          <ul class="question_list" v-for="(item, index) in dataList" :key="index">
            <li>
              <div v-for="(qItem, index2) in item.qOptions" :key="index2">
                <div class="radio_option_bar">
                  <p :class="qItem.bg_color"><b-form-radio :name="'question_option' + index" v-model="question_option[index]" :value="qItem.value" @change="itemSelected(qItem, item)"><span :class="qItem.text_color">{{ qItem.text }}</span></b-form-radio></p>
                </div>
              </div>
              <br>
            </li>
          </ul>

Now you have to use onchange method:

itemSelected (option, item) {
  if (option.is_correct) {
    option.bg_color = 'radio_option_correct_custom_design'
    option.text_color = 'text-success'
  } else {
    option.bg_color = 'radio_option_incorrect_custom_design'
    option.text_color = 'text-danger'
  }
}

Leave a comment