How to Show “Partially Selected” Checkboxes in Vue (Using indeterminate)

In many user interfaces, especially with grouped or hierarchical selections (like categories, projects, folders), you need more than just a checked or unchecked checkbox.

For example:

What if only some items in a group are selected?

Should the parent checkbox show checked, unchecked… or something else?

That’s where the indeterminate state comes in.

What is an indeterminate Checkbox?

An indeterminate checkbox is a visual cue that some, but not all, items in a group are selected.

It shows a dash (–) or a partially filled box, rather than a checkmark.

All Selected – ☑️ Checked

None Selected – ⬜ Unchecked

Some Selected – ➖ Indeterminate (partial)

You Can’t Set indeterminate in HTML

Unlike checked, the indeterminate state is not a standard HTML attribute — it can only be set via JavaScript or framework logic (like Vue).

Vue 3 Demo: Parent-Child Checkbox with indeterminate

Here’s a full Vue 3 example showing how to:

  • Track selected child checkboxes
  • Automatically update the parent checkbox to be:
  • ✅ Checked (all selected)
  • ⬜ Unchecked (none selected)
  • ➖ Indeterminate (some selected)
<template>
  <div class="p-4">
    <!-- Parent Checkbox -->
    <label>
      <input
        type="checkbox"
        :checked="allSelected"
        :indeterminate="someSelected && !allSelected"
        @change="toggleAll($event.target.checked)"
      />
      Select All Fruits
    </label>

    <!-- Child Checkboxes -->
    <div class="ml-6 mt-2">
      <label v-for="fruit in fruits" :key="fruit.name" class="block">
        <input
          type="checkbox"
          :checked="fruit.selected"
          @change="toggleFruit(fruit)"
        />
        {{ fruit.name }}
      </label>
    </div>
  </div>
</template>

<script setup>
import { reactive, computed } from 'vue';

const fruits = reactive([
  { name: 'Apple', selected: false },
  { name: 'Banana', selected: false },
  { name: 'Orange', selected: false }
]);

const allSelected = computed(() => fruits.every(f => f.selected));
const someSelected = computed(() => fruits.some(f => f.selected));

const toggleAll = (checked) => {
  fruits.forEach(f => f.selected = checked);
};

const toggleFruit = (fruit) => {
  fruit.selected = !fruit.selected;
};
</script>

Why This Matters

This pattern is used in many apps:

  • Selecting files or folders (Google Drive)
  • Toggling permissions or roles
  • Managing nested categories or filters

By showing a partial state visually, you make your UI more clear and user-friendly.

Summary

  • Use the indeterminate state to show “some items selected.”
  • You must set it with Vue’s reactivity or JavaScript, not HTML.
  • It greatly improves clarity in complex checkbox interfaces.

Leave a comment

Your email address will not be published. Required fields are marked *