Home > Back-end >  select all checkbox specific id
select all checkbox specific id

Time:09-23

I am working on a menu permission project using vue.js. I have some submenus which are child of different menus. I want to select all submenus of selected menu if I click on "select All". this is the code I am trying--

// New VueJS instance
var app = new Vue({
  el: "#app",
  data: {
    menus: [
      { id: 1, menuName: "Tech 1" },
      { id: 2, menuName: "Tech 2" },
      { id: 3, menuName: "Tech 3" }
    ],
    selectedAllSubMenu:[],
    selectedMenu: [],
    selectedSubMenu: [],
    submenus: [
      { id: 1, menuId: 1, subMenuName: "architecture" },
      { id: 2, menuId: 1, subMenuName: "Electrical" },
      { id: 3, menuId: 1, subMenuName: "Electronics" },
      { id: 4, menuId: 2, subMenuName: "IEM" },
      { id: 5, menuId: 3, subMenuName: "CIVIL" }
    ]
  },
  computed: {
    isUserInPreviousUsers() {
      return this.previousUsers.indexOf(this.userId) >= 0;
    },
    filteredProduct: function () {
      const app = this,
        menu = app.selectedMenu;

      if (menu.includes("0")) {
        return app.submenus;
      } else {
        return app.submenus.filter(function (item) {
          return menu.indexOf(item.menuId) >= 0;
        });
      }
    }
  },
  methods: {
    selectAllSubMenu(event) {
  for (let i = 0; i < this.submenus.length; i  ) {
    if (event.target.checked) {
      if (this.submenus[i].menuId == event.target.value) {
        this.selectedSubMenu.push(this.submenus[i].id);
      }
    } else {
      if (this.submenus[i].menuId == event.target.value) {
      var index = this.selectedSubMenu.indexOf(event.target.value);
      this.selectedSubMenu.splice(index, 1);
      }
    }
  }
},
    }
});
<!-- Include the library in the page -->
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>

<!-- App -->
<div id="app">
  <h4>Click on any menu. Then the submenus will appear. I want to select all submenus of selected menu if I click on "select All"</h4>
  <table >
    <thead>
      <tr>
        <th>Menu</th>
        <th>Submenu</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(menu,index) in menus" :key="menu.id">
        <td>
          <label>
            <input type="checkbox" :value="menu.id" v-model="selectedMenu" />{{ menu.menuName }}
          </label>
        </td>
        <td v-if="selectedMenu.length != 0">
          <ul>
             <label >
                                  <input
                                    type="checkbox"
                                    :value="menu.id"
                                    v-model="selectedAllSubMenu"
                                    @change="selectAllSubMenu"
                                  />
                                 Select all
                                </label>
            <li v-for="submenu in filteredProduct" :key="submenu.id" v-if="menu.id == submenu.menuId">

              <input type="checkbox" :value="submenu.id" v-model="selectedSubMenu" />
              <label>{{ submenu.subMenuName }} </label>

            </li>
          </ul>
        </td>
              </tr>
    </tbody>
  </table>

</div>

Here are some menus. every menu has some submenus. Now if I click on any submenu & then click on select all, all the submenus get selected. But the problem is, If I uncheck "select all" the previously selected submenus still got selected. How Do I solve this?

CodePudding user response:

Try like following snippet:

// New VueJS instance
var app = new Vue({
  el: "#app",
  data(){
    return {
      menus: [{ id: 1, menuName: "Tech 1" }, { id: 2, menuName: "Tech 2" }, { id: 3, menuName: "Tech 3" }],
      selectedMenu: [],
      selectedSubMenu: [],
      selectedAllSubMenu: [],
      submenus: [{ id: 1, menuId: 1, subMenuName: "architecture" }, { id: 2, menuId: 1, subMenuName: "Electrical" }, { id: 3, menuId: 1, subMenuName: "Electronics" }, { id: 4, menuId: 2, subMenuName: "IEM" }, { id: 5, menuId: 3, subMenuName: "CIVIL" }]
    }
  },
  computed: {
    isUserInPreviousUsers() {
      return this.previousUsers.indexOf(this.userId) >= 0;
    },
  },
  methods: {
    filteredProduct (id) {
      return this.submenus.filter(s => s.menuId === id)
    },
    selectSubMenu(id) {
      if (this.selectedSubMenu.filter(s => s.menuId === id).length === this.submenus.filter(s => s.menuId === id).length) {
        this.selectedAllSubMenu.push(id)
      } else {
        this.selectedAllSubMenu = this.selectedAllSubMenu.filter(s => s !== id)
      }
    },
    selectAllSubMenu(id){ 
      const checked = this.selectedAllSubMenu.some(s => s === id)
      if (this.selectedSubMenu.filter(s => s.menuId === id).length === this.submenus.filter(s => s.menuId === id).length && !checked) {
        this.selectedSubMenu = this.selectedSubMenu.filter(s => s.menuId !== id)
      } else if (checked) {
         this.selectedSubMenu = [... new Set([...this.selectedSubMenu].concat(this.submenus.filter(s => s.menuId === id)))]
      }
    },
  }
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">
  <table >
    <thead>
      <tr>
        <th>Menu</th>
        <th>Submenu</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="(menu,index) in menus" :key="menu.id">
        <td>
          <label>
            <input type="checkbox" :value="menu" v-model="selectedMenu" />{{ menu.menuName }}
          </label>
        </td>
        <td v-if="selectedMenu.filter(s => filteredProduct(menu.id).some(i => i.menuId === s.id)).length">
          <ul >
             <label >
              <input
                type="checkbox"
                :value="menu.id"
                v-model="selectedAllSubMenu"
                @change="selectAllSubMenu(menu.id)"
              />
             Select all
            </label>
            <li v-for="submenu in filteredProduct(menu.id)" :key="submenu.id">
              <input type="checkbox" :value="submenu" v-model="selectedSubMenu" @change="selectSubMenu(menu.id)" />
              <label>{{ submenu.subMenuName }} </label>
            </li>
          </ul>
        </td>
      </tr>
    </tbody>
  </table>
</div>

CodePudding user response:

After spending an hour on this requirement to find the root cause, I am here with a solution :

In your selectAllSubMenu method, splicing of the elements was not working properly as it was not able to remove the duplicate values from an array. Hence, I just changed a approach a bit. I am filtering the selectedSubMenu based on submenu ids of the selected menu.

selectAllSubMenu(event) {
  if (event.target.checked) {
    for (let i = 0; i < this.submenus.length; i  ) {
      if (this.submenus[i].menuId == event.target.value) {
        this.selectedSubMenu.push(this.submenus[i].id);
      }
    }
  } else {
    const filteredMenu = this.submenus.filter(obj => obj.menuId == event.target.value).map(({id}) => id);
    this.selectedSubMenu = this.selectedSubMenu.filter(el => filteredMenu.indexOf(el) === -1);
  }
}
  • Related