Home > Net >  Utilizing radio buttons to make a simple accordion in Vue
Utilizing radio buttons to make a simple accordion in Vue

Time:08-11

I'm trying to utilize radio buttons to make a simple accordion in vue. Everything works except I can't get the accordion to only show a single view at once.

Once the view has been expanded I seem to longer be able to close it without creating a separate v-model for the whole group and adding a conditional around it. Is it not possible to get a radio button to default to its off state after it is no longer selected?

    <div v-for="(item, index) in options">

      <label :for="'l'   item.name">{{ item.name }}</label>
      <input type="radio" :id="'l'   item.name" name="internalFinish" v-model="item.selected" :value="true">

      <div v-if="item.selected">
          <p>Accordion Open</p>
      </div>

    </div>

https://jsfiddle.net/s5ohgvde/

CodePudding user response:

I edited your code.I have simply added a new value for each record in the array as id.And a new data named selected with a @click event for the input. So it checks whether the id is equal to the selected item id, if so it will display only the relevant one. You can see the fiddle here https://jsfiddle.net/bugnrvt2/1/

      <label :for="'l'   item.name">{{ item.name }}</label>
      <input @click="selected = item.id" type="radio" :id="'l'   item.name" name="internalFinish" v-model="item.selected" :value="true">

      <div v-if="selected == item.id">
          <p>Accordion Open</p>
      </div>

  </div>
</div>



new Vue({
  el: "#app",
  data: {
    options : [
      { 
          name          : 'Plasterboard with Skim Finish',
          range         : false,
          selected      : false,
          selectedValue : 0,
          id: 1
      },
      { 
          name          : 'Plasterboard on Dabs',
          range         : { min : 0, max : 100},
          selected      : false,
          selectedValue : 0,
          id: 2
      },
      { 
          name          : 'Plaster Finish',
          range         : { min : 60, max : 100},
          selected      : false,
          selectedValue : 0,
          id: 3
      },
    ],
    selected: 0
  }
})

CodePudding user response:

Bind the radio input value to unique value like item.name then bind the v-model to another property which will be used as condition in v-if=

<div id="app">
  <div v-for="(item, index) in options">

      <label :for="'l'   item.name">{{ item.name }}</label>
      <input type="radio" :id="'l'   item.name" name="internalFinish" v-model="selectedOption" :value="item.name" >

      <div v-if="item.name===selectedOption">
          <p>Accordion Open</p>
      </div>

  </div>
</div>
<script>
new Vue({
  el: "#app",
  data: {
   selectedOption:null,
    options : [
      { 
          name          : 'Plasterboard with Skim Finish',
          range         : false,
          selected      : false,
          selectedValue : 0
      },
      { 
          name          : 'Plasterboard on Dabs',
          range         : { min : 0, max : 100},
          selected      : false,
          selectedValue : 0
      },
      { 
          name          : 'Plaster Finish',
          range         : { min : 60, max : 100},
          selected      : false,
          selectedValue : 0
      },
    ]
  }
})
</script>

CodePudding user response:

I would recommend doing something like this instead of a radio button or atleast try with a checkbox because checkbox can either hold true or false but its not so in case of radio button

new Vue({
  el: "#app",
  data: {
    selectedRow: null,
    options : [
      { 
          name          : 'Plasterboard with Skim Finish',
          range         : false,
          selected      : false,
          selectedValue : 0
      },
      { 
          name          : 'Plasterboard on Dabs',
          range         : { min : 0, max : 100},
          selected      : false,
          selectedValue : 0
      },
      { 
          name          : 'Plaster Finish',
          range         : { min : 60, max : 100},
          selected      : false,
          selectedValue : 0
      },
    ]
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="(item, index) in options">

      <label :for="'l'   item.name">{{ item.name }}</label>
      <!-- <input type="checkbox" :id="'l'   item.name" name="internalFinish" v-model="item.selected" :value="true">-->
      <span :id="'l'   item.name" name="internalFinish"  @click="selectedRow = item.name">
      <span v-if="selectedRow === item.name">&#9650</span>
      <span v-else>&#9660;</span></span>
      <div v-if="selectedRow === item.name">
          <p>Accordion Open</p>
      </div>

  </div>
</div>

CodePudding user response:

Thanks for the suggestions, I ended up reseting each option to selected = false on change.

    unselectOthers(index) {
                for (var i = this.options.length - 1; i >= 0; i--) {
                    if (i != index) {
                        this.options[i].selected = false;
                    }
                }
            }
<input type="radio" :id="'l'   item.name" name="internalFinish" v-model="item.selected" :value="item.name" @change.prevent="unselectOthers(index)">
  • Related