Reputation: 147
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
Upvotes: 9
Views: 13148
Reputation: 338
Simple example
<template>
<input
type="checkbox"
:indeterminate="isIndeterminate"
:checked="isChecked"
:value="modelValue"
@input="$emit('update:modelValue', isChecked)"
@click="toggleCheckState"
/>
</template>
<script setup lang="ts">
const props = defineProps({
modelValue: { type: Boolean, default: undefined }
})
defineEmits(['update:modelValue'])
import { onMounted, ref } from 'vue'
const isChecked = ref<boolean | undefined>(false)
const isIndeterminate = ref(false)
onMounted(() => {
if (props.modelValue == undefined) isIndeterminate.value = true
else isChecked.value = props.modelValue
})
function toggleCheckState() {
if (isIndeterminate.value) {
isChecked.value = true
isIndeterminate.value = false
} else if (isChecked.value == false) {
isChecked.value = undefined
isIndeterminate.value = true
} else {
isChecked.value = false
isIndeterminate.value = false
}
}
</script>
Usage
<SmartCheckbox v-model="anyRef" />
{{ anyRef}}
Upvotes: 0
Reputation: 596
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>
Upvotes: 1
Reputation: 211
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.
Upvotes: 21