Multi-check box components and bubble components from Ant-Design are used.

1. Data format



Val indicates the value of the selected box, selected indicates whether the element’s city is selected, and tag indicates that the selected box is selected. If the element is the first level, its city tags are all true. Show indicates whether to display the checkbox ~ on the page

Part 2. HTML

Picture 1.



The bubble component displays the corresponding city value when the mouse moves over the level 1 value

Code 2.

<template>
  <div class="box">
    <div class="box-option">
      <div :style="{ borderBottom: '1px solid #E9E9E9' }">
        <a-checkbox
          :indeterminate="indeterminate"
          :checked="checkAll"
          @change="onCheckAllChange"
        >
          Check all
        </a-checkbox>
      </div>
      <br />
      <div v-for="(item, index) in plainOptions" :key="item.val">
        <a-checkbox
          v-if="item.show"
          :indeterminate="item.selectd"
          :checked="item.tag"
          @change="(e) => onChangePro(index, e)"
        >
          <a-popover placement="bottom">
            <template slot="content">
              <div v-for="(city, cityIndex) in item.city" :key="cityIndex">
                <a-checkbox
                  v-if="city.show"
                  :checked="city.tag"
                  @change="(e) => onchangeCity(index, cityIndex, e)"
                >
                  {{ city.val }}
                </a-checkbox>
              </div>
            </template>
            <template slot="title"></template>
            {{ item.val }}
          </a-popover>
        </a-checkbox>
      </div>
    </div>
    <div class="box-result">
      <a-button type="primary" @click="onSubmitSelected">submit</a-button>
      <div v-for="(item, index) in resultList" :key="index" class="row-data">
        <h3 v-for="(val, idx) in item" :key="idx">{{ val }}</h3>
        <a-button @click="onUpdateResult(item, index)">Modify the</a-button>
        <a-button @click="onDeleteResult(item, index)">delete</a-button>
      </div>
    </div>
  </div>
</template>
Copy the code

Part 3. Js

Picture 1.

Code 2.

export default {
  data() {
    return {
      indeterminate: false.checkAll: false.plainOptions: [].resultList: [],}; },watch: {
    // Notice the listening array
    plainOptions: {
      handler(newVal, oldVal) {
        // Don't forget to show
        // If the tag in newVal is true and is displayed on the page, indeterminate is true
        // If all tags are tags, then indeterminate is false and checkAll is true
        let falg = false;
        newVal.forEach((v) = > {
          if (falg) {
            return;
          }
          v.city.forEach((k) = > {
            if (k.tag && k.show) {
              this.indeterminate = true;
              this.checkAll = false;
              falg = true;
              return; }}); });/ / all
        let res = newVal.every((v) = > {
          return v.tag == true;
        });
        this.checkAll = res;
        if (res) {
          this.indeterminate = false;
        }
        / / don't choose
        if(! falg) {this.indeterminate = false; }},deep: true,}},mounted() {
    this.getData();
  },
  methods: {
    getData() {
      this.$axios.get("/data/casc-demo.json").then((res) = > {
        this.plainOptions = res.data;
      });
    },
    onChangePro(index, e) {
      this.plainOptions[index].tag = e.target.checked;
      this.plainOptions[index].selectd = false;
      this.handleProSelected(this.plainOptions[index]);
    },
    onchangeCity(index, cityIndex, e) {
      this.plainOptions[index].city[cityIndex].tag = e.target.checked;
      this.handleCitySelected(this.plainOptions[index], cityIndex);
    },
    onCheckAllChange(e) {
      // All data changes according to the value e
      this.plainOptions.forEach((v) = > {
        v.tag = e.target.checked;
        v.selectd = false;
        v.city.forEach((k) = > {
          k.tag = e.target.checked;
        });
      });
    },
    // Provincial selection, if selected will affect the city
    handleProSelected(proData) {
      proData.city.forEach((v) = > {
        v.tag = proData.tag;
      });
    },
    // Select a city and check whether the provincial level needs to be selected
    handleCitySelected(proData, cityIndex) {
      let countTag = 0;
      proData.city.forEach((v) = > {
        if(v.tag) { countTag++; }});if (countTag == 0) {
        proData.tag = false;
        proData.selectd = false;
      } else if (countTag == proData.city.length) {
        proData.tag = true;
        proData.selectd = false;
      } else {
        proData.tag = false;
        proData.selectd = true; }},/* Submit data, set the selected data show to false, so that next time it will not show the selected data, but also modify the function if the provincial tag is true, then the provincial and municipal show is false, if the provincial tag is true, then the provincial and municipal show is false. Show = true; show = false; val = false Can only be found one by one, because the back end returns the same */
    onSubmitSelected() {
      let submitData = [];
      this.plainOptions.forEach((v) = > {
        if (v.tag && v.show) {
          v.show = false;
          v.city.forEach((k) = > {
            k.show = false;
            submitData.push(k.val);
          });
        } else if (v.selectd) {
          v.selectd = false;
          v.city.forEach((k) = > {
            if (k.tag && k.show) {
              k.show = false; submitData.push(k.val); }}); }});this.resultList.push(submitData);
    },
    // Modify table data
    onUpdateResult(val, idx) {
      // Put the value of the argument back into the array
      this.handleChangeOptions(val, "update");
    },
    // Delete the line
    onDeleteResult(val, idx) {
      this.resultList.splice(idx, 1);
      this.handleChangeOptions(val, "delete");
    },
    /* create a function that can be easily deleted and modified by iterating through the number groups and modifying the show and tag groups */
    handleChangeOptions(val, type) {
      val.forEach((v) = > {
        this.plainOptions.forEach((k) = > {
          let flag = false;
          k.city.forEach((z) = > {
            if (v == z.val) {
              if (type == "delete") {
                z.tag = false;
              }
              z.show = true;
              flag = true; }});if (flag) {
            if (type == "delete") {
              k.tag = false;
              k.selectd = false;
            } else if (k.tag) {
              k.selectd = false;
            } else {
              k.selectd = true;
            }
            k.show = true; }}); }); ,}}};Copy the code

3. The CSS part

.box {
  margin: 20px;
}

.box-option {
  padding-bottom: 100px;
}

.box-result {
  padding-top: 20px;
}
.row-data {
  display: flex;
  padding: 10px 0;
  border-bottom: 1px solid forestgreen;
}
h3 {
  padding: 0 10px;
}
Copy the code