Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VueJS Master Checkbox Toggle with array values

I am using VueJS and am having a problem implementing two features on a series of checkboxes.

  • Firstly, my checkboxes are build dynamically.
  • I need to implement a master 'toggle' checkbox which when clicked either checks or un-checks all other checkboxes.
  • I need to keep an array of checked items in the model.

This script gives me the toggle checkbox, but does not populate the "checkedNames" array. I have tried adding a v-model to the names checkboxes but that just checked everything and still doesn't populate the array.

new Vue({
  el: '#boxes',
  data: {
    checked: null,
    checkedNames: [],
    teams: [{
        name: 'team a',
        id: 'team-a',
        checked: null,
        members: [{
            'id': 1,
            'name': 'Dave'
          },
          {
            'id': 2,
            'name': 'Dee'
          },
          {
            'id': 3,
            'name': 'Dozy'
          },
          {
            'id': 4,
            'name': 'Beaky'
          },
          {
            'id': 5,
            'name': 'Mick'
          },
          {
            'id': 6,
            'name': 'Tich'
          }
        ]
      },
      {
        name: 'team b',
        id: 'team-b',
        checked: null,
        members: [{
            'id': 7,
            'name': 'John'
          },
          {
            'id': 8,
            'name': 'Paul'
          },
          {
            'id': 9,
            'name': 'George'
          },
          {
            'id': 10,
            'name': 'Ringo'
          }
        ]
      }
    ]
  }
});
<div id='boxes'>
  <ul>
    <li v-for="team in teams" style="width: 100px; float:left">
      <div>
        <input type="checkbox" class="form-check form-check-inline" v-bind:id="team.id" v-model="team.checked">
        <label v-bind:for="team.id"><strong>{{ team.name }}</strong></label>
      </div>
      <ul class="countries_list">
        <li v-for="member in team.members">
          <input type="checkbox" class="form-check form-check-inline" v-bind:id="member.id" v-bind.checked="{checked : team.checked}">
          <label v-bind:for="member.id">{{ member.name }}</label>
        </li>
      </ul>
    </li>
  </ul>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

https://jsfiddle.net/50wL7mdz/133578/

Is anyone able to point me in the right direction?

like image 592
Typhoon101 Avatar asked Aug 02 '26 02:08

Typhoon101


2 Answers

My opinion:

1. added 'checked' attribute for each member.

2. bind the checkbox of each member with v-model="member.checked" for each member

3. bind 'change' event for team checkbox, if clicked, set member.checked=team.checked for each member

4. convert checkedNamed to computed atrribute, use for-loop or reduce to print out all members are checked.

new Vue({
  el: '#boxes',
  computed: {
    computed_checkedNames: function() {
      let temp = '';
      for(teamIndex in this.teams) {
        temp += '[team=' + this.teams[teamIndex].name + ']{'
        for(memberIndex in this.teams[teamIndex].members) {
          temp += this.teams[teamIndex].members[memberIndex].checked ? this.teams[teamIndex].members[memberIndex].name + ',' : ''
        }
        temp += '},'
      }
      
      return temp
    }
  },
  data: {
    checked: null,
    //checkedNames: [],
    teams: [{
        name: 'team a',
        id: 'team-a',
        checked: false,
        members: [{
            'id': 1,
            'name': 'Dave',
            checked: false
          },
          {
            'id': 2,
            'name': 'Dee',
            checked: false
          },
          {
            'id': 3,
            'name': 'Dozy',
            checked: false
          },
          {
            'id': 4,
            'name': 'Beaky',
            checked: false
          },
          {
            'id': 5,
            'name': 'Mick',
            checked: false
          },
          {
            'id': 6,
            'name': 'Tich',
            checked: false
          }
        ]
      },
      {
        name: 'team b',
        id: 'team-b',
        checked: null,
        members: [{
            'id': 1,
            'name': 'John',
            checked: false
          },
          {
            'id': 2,
            'name': 'Paul',
            checked: false
          },
          {
            'id': 3,
            'name': 'George',
            checked: false
          },
          {
            'id': 4,
            'name': 'Ringo',
            checked: false
          },
          {
            'id': 6,
            'name': 'Tich',
            checked: false
          }
        ]
      }
    ]
  }
});
<div id='boxes'>
  <ul>
    <li v-for="team in teams" style="width: 100px; float:left">
      <div>
        <input type="checkbox" class="form-check form-check-inline" v-bind:id="team.id" v-model="team.checked" v-on:change="team.members.forEach(function(value, key){value.checked=team.checked});">
        <label v-bind:for="team.id"><strong>{{ team.name }}</strong></label>
      </div>
      <ul class="countries_list">
        <li v-for="member in team.members">
          <input type="checkbox" class="form-check form-check-inline" v-bind:id="member.id"  v-model="member.checked">
          <label v-bind:for="member.id">{{ member.name }}</label>
        </li>
      </ul>
    </li>
  </ul>
  <br>
  <span style="background-color:#8d9bb2">Checked names: {{ computed_checkedNames }}</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
like image 92
Sphinx Avatar answered Aug 03 '26 16:08

Sphinx


This is a bit tricky. I think you need to control everything using @change as you have your checkAll checkboxes feature.

In my side, I don't need those parent checked properties, all I need is the children checked property to distinguised either checked/unchecked. Basically this is a fallback as you have to add extra property checked.

Check and try to run the snippet below.

new Vue({
        el : '#boxes',
        data : {
            teams: [
                {
                    name: 'team a',
                    id: 'team-a',
                    members: [
                        {'id': 1, 'name' : 'Dave', 'checked': false},
                        {'id': 2, 'name' : 'Dee', 'checked': false},
                        {'id': 3, 'name' : 'Dozy', 'checked': false},
                        {'id': 4, 'name' : 'Beaky', 'checked': true},
                        {'id': 5, 'name' : 'Mick', 'checked': false},
                        {'id': 6, 'name' : 'Tich', 'checked': false}
                    ]
                },
                {
                    name: 'team b',
                    id: 'team-b',
                    members: [
                        {'id': 7, 'name' : 'John', 'checked': false},
                        {'id': 8, 'name' : 'Paul', 'checked': false},
                        {'id': 9, 'name' : 'George', 'checked': false},
                        {'id': 10, 'name' : 'Ringo', 'checked': false},
                        {'id': 11, 'name' : 'Mick', 'checked': false}
                    ]
                }
            ]
        },
        computed: {
          getSelectedMembers: function() {
            var selectedMem = [];
            for(var teamIdx in this.teams) {
              var members = this.teams[teamIdx].members;
              for(var memberIdx in members) {
                if (members[memberIdx].checked) {
                  selectedMem.push(members[memberIdx].id);
                }
              }
            }
            return selectedMem;
          }
        },
        methods: {
          checkAll: function(idx, $event) {
            var member = this.teams[idx].members;
            for(var memberIdx in member) {
              member[memberIdx].checked = $event.target.checked;
            }
          }
        }
    });
.disp {
  display: inline-block;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/vue"></script>

<div id='boxes'>
    <ul>
        <li v-for="(team, index) in teams" style="width: 200px; float:left">
            <div>
                <input type="checkbox" class="form-check form-check-inline" v-bind:id="team.id" @change="checkAll(index, $event)" >
                <label v-bind:for="team.id"><strong>{{ team.name }}</strong></label>
            </div>
            <ul class="countries_list">
                <li v-for="member in team.members">
                    <input type="checkbox" class="form-check form-check-inline" v-bind:id="member.id" v-bind.checked="{checked : member.checked}" :value="member.name" @change="member.checked = !member.checked">
                    <label v-bind:for="member.id">{{ member.name }}</label>
                </li>
            </ul>
        </li>
    </ul>
    <div>getSelectedMembers: {{ getSelectedMembers }}</div>
    <br><br><br><br><br><br><br><br><br>
    <div class="disp" v-for="team in teams">
      <ul><strong>{{ team.id }}</strong>
        <li v-for="member in team.members" v-if="member.checked">{{member.name}}</li>
      </ul>
    </div>
    
</div>
like image 35
Dencio Avatar answered Aug 03 '26 15:08

Dencio



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!