Search code examples
javascriptvue.jsvuejs2vue-componentbootstrap-vue

How set computed property of checked checkboxes via v-model?


I've looked several resources, but I don't find the solution:

I've a table with people that have roles, if I want to change the roles I open a modal.

<template>
  <div>
    <b-table small outlined striped hover :items="peoplePaginated.data" :fields="fields" >
      <template slot="actions" slot-scope="row">
        <b-button size="sm" class="my-2 my-sm-0 btn-outline-info" v-b-modal="'federation-role-modal'" @click.stop="change(row.item)">
        edit
        </b-button>
        <b-button size="sm" @click.stop="info(row.item, row.index, $event.target)" class="btn btn-outline-success btn-sm">
          details
        </b-button>
      </template>
    </b-table>
    <FederationRoleModal :roles="roles" />
  </div>
</template>


data () {
 return {
    roles: [],
 }
},


  methods: {
    info (item) {
      this.$router.push({ name: 'person', params: { id: item.id }})
    },
    change (person) {
      const roles = person.personRoles.map(el => el)
      const allRoles = roles.map(el => el.roleCategory.name)
      this.roles = allRoles
    }
  }

Then I've a list of checkboxes where the checkedRoles takes care of the checked ones. When I click on a new checkbox, I want the data property to be updated. However this updating does not happen.

In the modal:

<span v-for="value in allRoles" :key="value.id">
    <input type="checkbox" :value="value" v-model="checkedRoles">
    <span class="checkbox-label"> {{value}} </span> <br>
</span>



computed property: {
  checkedRoles: {
    get: function () {
      // console.log(this.roles)
      return this.roles
    },
    set: function (newValue) {
      // console.log(newValue)
      return newValue
    }
  }
}

this.roles comes from the parent component (array with roles). I do see the console.log(newValue) output as a new array with an additional role, but this new array is not visible as the checkedRoles data property.

  • [option 2] I've also tried to add checkedRoles: this.roles, in the data () { return {... }. But when I open several times a modal, the roles of the previous clicked row.item are still in the data property.

Please advise

  1. if I should be using a computed property, or dig deeper into [option 2]

  2. how I get all checked checkboxes to be in the checkedRoles data property.


Solution

  • Solution included modifying the parent component data property:

    In the parent component add:

    <FederationRoleModal :checked-roles="roles" @update-role="onUpdateRole"/>
    

    methods:

        onUpdateRole(value) {
          let rolesArray = this.roles
          if (rolesArray.includes(value)){
            var index = rolesArray.indexOf(value)
            if (index > -1) {
              return rolesArray.splice(index, 1);
            }
          } else {
            return rolesArray.push(value)
          }
        }
    

    in the child component

          <span v-for="value in allRoles" :key="value.id">
            <input type="checkbox" :value="value" v-model="roles" @click="$emit('update-role', value)">
            <span class="checkbox-label"> {{value}} </span> <br>
          </span>
    

    data:

    props: ['checkedRoles'],
    

    computed:

    roles: {
      get: function () {
       return this.checkedRoles
     },
     set: function (newValue) {
       return newValue
     }
    }