Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue indeterminate checkbox binding

I am using vue for data binding. I want to create a widget for access level control so I need allow, deny, and indeterminate states.

This markup is good but there is no indeterminate state:

<div class="row" v-for='a in context.This.Actions'>
    <div class="col-96">
        <input class="custom-control-input access-checkbox" v-bind:id="'chk_'+a.Name" v-bind:value="a.Id" v-model="context.This.RoleActions" indeterminate="true" type="checkbox" />
        <label class="pointer" v-bind:for="'chk_'+a.Name">{{ a.Name }}</label>
    </div>
</div>

The variables are :

context.This.Actions = [
    { "Id": "id_1",
      "Name": "AAA"
    },
    { "Id": "id_2",
      "Name": "BBB"
    },
    { "Id": "id_3",
      "Name": "CCC"
    }
]

context.This.RoleActions = [ "id_1", "id_2" ]

I want this change:

context.This.RoleActions = [ {"id_1":true}, {"id_2":false} ]

and I expect the below result:

  • The first checkbox: checked

  • The second checkbox: unchecked

  • The other one: indeterminate

like image 934
Mohsen Mirshahreza Avatar asked May 09 '17 03:05

Mohsen Mirshahreza


People also ask

How do I set an indeterminate checkbox?

A checkbox cannot be set to indeterminate state by an HTML attribute - it must be set by a JavaScript. This state can be used to force the user to check or uncheck the checkbox.

How do you check checkbox is checked or not in VUE JS?

prop('checked'); which will return true if checkbox is checked or not.


2 Answers

Indeterminate is a DOM property on a checkbox, which means putting it in the markup won't have an effect, it needs to be applied programmatically.

Even after doing that, keep in mind the state of a checkbox is still either checked or not checked. This is important to keep in mind when processing the form. The difference is visual only. (source)

With those caveats in mind, in Vue 2 you can add an indeterminate property to a checkbox like so:

<input type="checkbox" indeterminate.prop="true">

or bind to a dynamic value in your component:

<input type="checkbox" :indeterminate.prop="dataProperty">

I would recommend refactoring with this in mind.

like image 86
Tim D Avatar answered Oct 07 '22 13:10

Tim D


I had a similar issue using props with checkbox to support 2 and 3 states . to handle this I used computed property with getter and setter using Vuetify checkbox

Here is my example

<template>
  <v-container class="checkbox-container">
    <v-checkbox
      type="checkbox"
      :indeterminate="indeterminate"
      :color="indeterminate ? '#767575' : 'success'"
      v-model="internalState"
      @click.stop="onCheckbox"
      @keyup.space.prevent="onCheckbox"
    ></v-checkbox>
  </v-container>
</template>

<script>
/**
 * Responsability: boolean field editor checkbox
 * When @threeState is true : following states (check, uncheck, indeterminate) otherwise (check, uncheck)
 * @checkboxState is an external state where it contains always the current state of checkbox
 **/
export default {
  model: {
    // v-model prop
    prop: 'checkboxState',
  },
  props: {
    threeState: Boolean,
    /**
     * Init state is the starting state Which the chekbox starts from.
     * by defining initstate it will ignore the default input @boolProperty
     **/
    initState: {
      type: String,
      default: 'false',
    },
    // Reperesent the value of checked state in model
    config: {
      type: Object,
      default: () => ({
        checked: 'true',
        unchecked: 'false',
        indeterminate: null,
      }),
    },
    checkboxState: {
      type: String,
    },
  },

  data() {
    return {
      internalState: this.checkboxState,
      indeterminate: false,
    }
  },

  computed: {
    state: {
      get() {
        return this.checkboxState
      },
      set(newState) {
        this.changeCheckboxState(newState)
      },
    },
  },

  // Change the state of checkbox after DOM is mounted
  mounted() {
    this.changeCheckboxState(this.initState)
  },

  methods: {
    changeCheckboxState(state) {
      this.$vnode.data.model.callback(state)
      this.internalState = state === this.config.checked
      this.indeterminate = state === this.config.indeterminate
    },

    onCheckbox() {
      if (this.threeState) {
        switch (this.state) {
          case this.config.unchecked:
            this.state = this.config.checked
            break
          case this.config.checked:
            this.state = this.config.indeterminate
            break
          case this.config.indeterminate:
            this.state = this.config.unchecked
            break
        }
      } else {
        this.state = (!(this.state === this.config.checked)).toString()
      }
    },
  },
}
</script>

<style lang="scss" scoped>
.checkbox-container {
  width: 50px;
}
</style>
like image 26
Martin Seydo Avatar answered Oct 07 '22 12:10

Martin Seydo