Mike L.
Mike L.

Reputation: 343

Select all checkbox vue

I'm trying to create the following:

I receive an array of objects. Each object consists of an id, an option, and a group name. I need to output the data in a way that firstly I have a checkbox with a value of a group name property and then a list of checkboxes which have the same group properties. For instance, let's say I recieve the following data:

[
{id:1, text: 'Football', group: 'sport'}
{id:2, text: 'Basketball', group: 'sport'}
{id:3, text: 'Cookie', group: 'food'}
{id:4, text: 'Soup', group: 'food'}
]

So the output should be the following:

<checkbox which when clicked should select all checkboxes belonging to this group>Sport</checkbox>
<checkbox>Football</checkbox>
<checkbox>Basketball</checkbox>


<checkbox which when clicked should select all checkboxes belonging to this group>Food</checkbox>
<checkbox>Cookie</checkbox>
<checkbox>Soup</checkbox>

So far I have the following:

export default {
        data() {
            return {
                actionTypes: actionTypes,
                relationTypes: relationTypes,
                optionsList: [
                              {id:1, text: 'Football', group: 'sport'}
                              {id:2, text: 'Basketball', group: 'sport'}
                              {id:3, text: 'Cookie', group: 'food'}
                              {id:4, text: 'Soup', group: 'food'}
                              ]
                optionsGroupsList: ['Sport', 'Food'],
                localValue: []
        },
<link href="https://cdn.jsdelivr.net/npm/vuesax/dist/vuesax.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div
        v-for="group in optionsGroupsList"
        class="checkbox-group">
        <vs-checkbox
          :vs-value="group"
          :key="group"
        >
          {{ group }}
        </vs-checkbox>
        <vs-checkbox
          v-for="option in optionsList"
          v-if="option.group === group"
          :vs-value="option.id"
          :key="option.id"
          v-model="localValue"
        >
          {{ option.text }}
        </vs-checkbox>
      </div>

So I do receive the necessary output but I have no idea how to make the group checkboxes work in a way that they select the checkboxes belonging to them (to this group)

I would really appreciate any ideas, thanks in advance!

Upvotes: 0

Views: 320

Answers (1)

Mischa
Mischa

Reputation: 1601

  1. I would suggest you structure your data in a nested array of objects (here computed: nestedOptions -method) so that your data looks like this:
nestedOptions: [
  {
    name: "sport",
    options: [
      { id: 1, text: "Football", group: "sport" },
      { id: 2, text: "Basketball", group: "sport" },
    ]
  },
  {
    name:"food"
    options: [...]
  }
]
  1. Keep track of the selected options as well as the selected groups.
  2. Make a watcher for the selected groups ... if they change then change the selected options accordingly:
export default {
  name: "groupedOptionsComponent",
  data() {
    return {
      selectedOptions: [],
      selectedGroups: [],
      optionsList: [
        { id: 1, text: "Football", group: "sport" },
        { id: 2, text: "Basketball", group: "sport" },
        { id: 3, text: "Cookie", group: "food" },
        { id: 4, text: "Soup", group: "food" }
      ],
      optionsGroupsList: ["sport", "food"]
    };
  },
  computed: {
    nestedOptions() {
      return this.optionsGroupsList.map(groupName => ({
        name: groupName,
        options: this.optionsList.filter(({ group }) => group === groupName)
      }));
    }
  },
  watch: {
    selectedGroups: function(groups) {
      this.optionsList.forEach(option => {
        if (
          groups.includes(option.group) &&
          !this.selectedOptions.includes(option.id)
        ) {
          this.selectedOptions.push(option.id);
        } else {
          this.selectedOptions = this.optionsList
            .filter(({ group }) => groups.includes(group))
            .map(({ id }) => id);
        }
      });
    }
  }
};

Makes your Template look something like this:

<template>
  <div>
    <div v-for="(group, index) in nestedOptions" class="checkbox-group" :key="index">
      <vs-checkbox :vs-value="group.name" v-model="selectedGroups">{{ group.name }}</vs-checkbox>
      <vs-checkbox
        v-for="option in group.options"
        :vs-value="option.id"
        :key="option.id"
        v-model="selectedOptions"
      >{{ option.text }}</vs-checkbox>
    </div>
  </div>
</template>

Upvotes: 1

Related Questions