Home > Software engineering >  vue selecting one checkbox is affecting other checkboxes
vue selecting one checkbox is affecting other checkboxes

Time:09-22

I am working on menu-permissions using vue. I want assign "Edit", "create", "delete" on different menus. Now If I click on "create" checkbox of some menu, It is triggering other "create" checkboxes.

What I am trying is demonstrated on this codepen

How can I assign separate functionalities to separate menus?

console.clear();

// 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" }
    ],
    selectedActions: [],
    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: {
    setSelectedMenu: function (event, menu_id) {
      if (event.target.checked) {
        this.selectedMenu.push(menu_id);
      } else {
        var index = this.selectedMenu.indexOf(menu_id);
        this.selectedMenu.splice(index, 1);
      }
    }
  }
});
<!-- Include the library in the page -->
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>

<!-- App -->
<div id="app">
  <table >
    <thead>
      <tr>
        <th>Menu</th>
        <th>Submenu</th>
        <th>Actions</th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="menu in menus" :key="menu.id">
        <td>
          <label>
            <input type="checkbox" :value="menu.id" v-model="selectedMenu" />{{ menu.menuName }}
          </label>
        </td>
        <td>
          <ul>
            <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>
        <td >
          <label >
            <input type="checkbox" name="action[]" v-model="selectedActions" value="Create" />Create</label><br />
          <label >
            <input type="checkbox" name="action[]" v-model="selectedActions" value="Edit" />Edit</label><br />
          <label >
            <input type="checkbox" name="action[]" v-model="selectedActions" value="Delete" />Delete</label>
        </td>
      </tr>
    </tbody>
  </table>

</div>

CodePudding user response:

You can do it like in the snippet below.

The only thing changed is the value attribute of the Create, Edit and Delete inputs. Change it to :value="{name: 'Create', menu: index}" and then read the object as per need.

Here is a JSFiddle

console.clear();

// 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" }
      ],
      selectedActions: [],
      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: {
      setSelectedMenu: function (event, menu_id) {
        if (event.target.checked) {
          this.selectedMenu.push(menu_id);
        } else {
          var index = this.selectedMenu.indexOf(menu_id);
          this.selectedMenu.splice(index, 1);
        }
      }
    },
    watch: {
      selectedActions() {
        console.log(this.selectedActions)
      }
    }
});
<!-- Include the library in the page -->
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>

<!-- App -->
<div id="app">
  <table >
    <thead>
      <tr>
        <th>Menu</th>
        <th>Submenu</th>
        <th>Actions</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>
          <ul>
            <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>
        <td >
          <label >
            <input type="checkbox" name="action[]" v-model="selectedActions" :value="{name: 'Create', menu: index}" />Create</label><br />
          <label >
            <input type="checkbox" name="action[]" v-model="selectedActions" :value="{name: 'Edit', menu: index}" />Edit</label><br />
          <label >
            <input type="checkbox" name="action[]" v-model="selectedActions" :value="{name: 'Delete', menu: index}" />Delete</label>
        </td>
      </tr>
    </tbody>
  </table>

</div>

  • Related