
useGroup
The useGroup composable is designed to manage a group of related components, allowing for shared state and behavior across them. It supports tri-state (mixed/indeterminate) for checkbox trees and similar use cases where items can be selected, unselected, or in a mixed state.
Usage
The useGroup composable manages a group of selectable items, letting you work with both their IDs and their position indexes. It supports selecting, unselecting, toggling, and reading the indexes of selected items.
import { createGroup } from '@vuetify/v0'
// Instantiate group
const group = createGroup()
// Register items
group.register({ id: 'apple', value: 'Apple' })
group.register({ id: 'banana', value: 'Banana' })
group.register({ id: 'cherry', value: 'Cherry' })
group.register({ id: 'date', value: 'Date' })
// Select some items
group.select(['apple', 'banana'])
console.log(group.selectedIndexes.value) // Set { 0, 1 }
// Toggle an item (banana will become unselected)
group.toggle('banana')
console.log(group.selectedIndexes.value) // Set { 0 }
// Unselect apple
group.unselect('apple')
console.log(group.selectedIndexes.value) // Set {}Tri-State (Mixed/Indeterminate)
Items can be in one of three states: selected, mixed (indeterminate), or unselected. This is useful for checkbox trees where a parent’s state depends on its children.
import { createGroup } from '@vuetify/v0'
const group = createGroup()
group.onboard([
{ id: 'parent', value: 'All Items' },
{ id: 'child-1', value: 'Item 1' },
{ id: 'child-2', value: 'Item 2' },
])
// Set parent to mixed state (some children selected)
group.mix('parent')
console.log(group.mixed('parent')) // true
console.log(group.mixedIds) // Set { 'parent' }
// Selecting clears mixed state
group.select('parent')
console.log(group.mixed('parent')) // false
console.log(group.selectedIds.has('parent')) // true
// Toggle on a mixed item selects it
group.mix('parent')
group.toggle('parent')
console.log(group.selectedIds.has('parent')) // trueTri-State Checkbox Tree Example
<script setup>
import { createGroup } from '@vuetify/v0'
import { computed, ref, watchEffect } from 'vue'
const group = createGroup()
const parent = group.register({ id: 'parent', value: 'All Items' })
const children = group.onboard([
{ id: 'child-1', value: 'Item 1' },
{ id: 'child-2', value: 'Item 2' },
{ id: 'child-3', value: 'Item 3' },
])
// Compute parent state based on children
const allSelected = computed(() => children.every(c => c.isSelected.value))
const someSelected = computed(() => children.some(c => c.isSelected.value) && !allSelected.value)
// Sync parent state with children
watchEffect(() => {
if (allSelected.value) {
group.select('parent')
} else if (someSelected.value) {
group.mix('parent')
} else {
group.unselect('parent')
group.unmix('parent')
}
})
// Parent checkbox ref for indeterminate property
const parentCheckbox = ref()
watchEffect(() => {
if (parentCheckbox.value) {
parentCheckbox.value.indeterminate = parent.isMixed.value
}
})
function toggleParent() {
if (parent.isSelected.value) {
group.unselect(children.map(c => c.id))
} else {
group.select(children.map(c => c.id))
}
}
</script>
<template>
<div>
<label>
<input
ref="parentCheckbox"
type="checkbox"
:checked="parent.isSelected.value"
@change="toggleParent"
>
{{ parent.value }}
</label>
<div style="margin-left: 1.5rem">
<label v-for="child in children" :key="child.id">
<input
type="checkbox"
:checked="child.isSelected.value"
@change="child.toggle()"
>
{{ child.value }}
</label>
</div>
</div>
</template>Select All
For simpler “select all” checkbox patterns, useGroup provides context-level helpers that work on all selectable (non-disabled) items at once:
isNoneSelected: True when no items are selectedisAllSelected: True when all selectable items are selectedisIndeterminate: True when some but not all are selectedselectAll(): Selects all non-disabled itemsunselectAll(): Unselects all items (respects mandatory option)toggleAll(): Toggles between all selected and none selected
See the #Group component for a complete example.
API
| Composable | Description |
|---|---|
| useSelection→ | Base selection system that useGroup extends |
| useSingle→ | Single-selection variant |
| useFeatures→ | Feature flags system (extends useGroup) |
| useRegistry→ | Base registry system |
Type
export interface GroupTicket extends SelectionTicket { isMixed: Readonly<Ref<boolean>> mix: () => void unmix: () => void } export interface GroupContext<Z extends GroupTicket> extends SelectionContext<Z> { selectedIndexes: ComputedRef<Set<number>> select: (ids: ID | ID[]) => void unselect: (ids: ID | ID[]) => void toggle: (ids: ID | ID[]) => void mixedIds: Reactive<Set<ID>> mixedItems: ComputedRef<Set<Z>> mix: (ids: ID | ID[]) => void unmix: (ids: ID | ID[]) => void mixed: (id: ID) => boolean isNoneSelected: ComputedRef<boolean> isAllSelected: ComputedRef<boolean> isIndeterminate: ComputedRef<boolean> selectAll: () => void unselectAll: () => void toggleAll: () => void } export interface GroupOptions extends SelectionOptions {}Details
selectedIndexes: Computed Set of numeric indexes for all currently selected items.select(ids): Marks one or more items as selected. Clears mixed state.unselect(ids): Marks one or more items as unselected.toggle(ids): Switches selection state. Mixed items become selected.mixedIds: Reactive Set of IDs in mixed/indeterminate state.mixedItems: Computed Set of tickets in mixed state.mix(ids): Sets items to mixed state. Clears selected state.unmix(ids): Clears mixed state from items.mixed(id): Returns true if the item is in mixed state.isNoneSelected: True when no items are selected.isAllSelected: True when all selectable (non-disabled) items are selected.isIndeterminate: True when some but not all selectable items are selected.selectAll(): Selects all non-disabled items. Clears mixed state on selected items.unselectAll(): Clears selection. Respects mandatory option (keeps one item).toggleAll(): Selects all if not all selected, otherwise unselects all.
selectedIndexes
Type
ComputedRef<Set<number>>Details A Set of numeric indexes for all currently selected items. Useful when selection state is tied to the order of registered items.
Example
const group = createGroup() group.register({ id: 'apple', value: 'Apple' }) group.register({ id: 'banana', value: 'Banana' }) group.select(['apple', 'banana']) console.log(group.selectedIndexes.value) // Set { 0, 1 }
select
Type
function select(ids: ID | ID[]): voidDetails Selects the given item(s). Clears any mixed state on the items before selecting.
Example
const group = createGroup() group.register({ id: 'apple', value: 'Apple' }) group.register({ id: 'banana', value: 'Banana' }) group.select('apple') group.select(['banana']) console.log(group.selectedIndexes.value) // Set { 0, 1 }
unselect
Type
function unselect(ids: ID | ID[]): voidDetails Unselects the given item(s), removing them from the active selection.
Example
const group = createGroup() group.register({ id: 'apple', value: 'Apple' }) group.register({ id: 'banana', value: 'Banana' }) group.select(['apple', 'banana']) group.unselect('banana') console.log(group.selectedIndexes.value) // Set { 0 }
toggle
Type
function toggle(ids: ID | ID[]): voidDetails Flips the selection state of the given item(s):
- If selected, becomes unselected.
- If unselected, becomes selected.
- If mixed, becomes selected (resolves indeterminate state positively).
Example
const group = createGroup() group.register({ id: 'apple', value: 'Apple' }) group.toggle('apple') console.log(group.selectedIds.has('apple')) // true group.toggle('apple') console.log(group.selectedIds.has('apple')) // false
mix
Type
function mix(ids: ID | ID[]): voidDetails Sets the given item(s) to mixed/indeterminate state. Clears selected state if set. Works on disabled items since mixed state is typically computed, not user-driven.
Example
const group = createGroup() group.register({ id: 'parent', value: 'Parent' }) group.mix('parent') console.log(group.mixed('parent')) // true console.log(group.mixedIds) // Set { 'parent' }
unmix
Type
function unmix(ids: ID | ID[]): voidDetails Clears mixed/indeterminate state from the given item(s).
Example
const group = createGroup() group.register({ id: 'parent', value: 'Parent' }) group.mix('parent') group.unmix('parent') console.log(group.mixed('parent')) // false
mixed
Type
function mixed(id: ID): booleanDetails Returns true if the given item is in mixed/indeterminate state.
Example
const group = createGroup() group.register({ id: 'parent', value: 'Parent' }) console.log(group.mixed('parent')) // false group.mix('parent') console.log(group.mixed('parent')) // true
mixedIds
Type
Reactive<Set<ID>>Details A reactive Set containing the IDs of all items currently in mixed/indeterminate state.
Example
const group = createGroup() group.onboard([ { id: 'a', value: 'A' }, { id: 'b', value: 'B' }, ]) group.mix(['a', 'b']) console.log(group.mixedIds) // Set { 'a', 'b' }
mixedItems
Type
ComputedRef<Set<GroupTicket>>Details A computed Set containing the ticket objects for all items in mixed state.
Example
const group = createGroup() group.register({ id: 'parent', value: 'Parent' }) group.mix('parent') const items = Array.from(group.mixedItems.value) console.log(items[0].value) // 'Parent'
Ticket Properties
Each registered ticket has these mixed-related properties:
isMixed:Readonly<Ref<boolean>>- Reactive property indicating mixed state.mix():() => void- Sets this ticket to mixed state.unmix():() => void- Clears mixed state from this ticket.
const group = createGroup()
const ticket = group.register({ id: 'item', value: 'Item' })
ticket.mix()
console.log(ticket.isMixed.value) // true
ticket.unmix()
console.log(ticket.isMixed.value) // falseisNoneSelected
Type
ComputedRef<boolean>Details Returns true when no items are currently selected. Useful for determining if a “select all” checkbox should be unchecked.
Example
const group = createGroup() group.onboard([ { id: 'a', value: 'A' }, { id: 'b', value: 'B' }, ]) console.log(group.isNoneSelected.value) // true group.select('a') console.log(group.isNoneSelected.value) // false
isAllSelected
Type
ComputedRef<boolean>Details Returns true when all selectable (non-disabled) items are selected. Returns false when the registry is empty or all items are disabled.
Example
const group = createGroup() group.onboard([ { id: 'a', value: 'A' }, { id: 'b', value: 'B', disabled: true }, ]) group.select('a') console.log(group.isAllSelected.value) // true (disabled items don't count)
isIndeterminate
Type
ComputedRef<boolean>Details Returns true when some but not all selectable items are selected. This is useful for setting the indeterminate state on a “select all” checkbox.
Example
const group = createGroup() group.onboard([ { id: 'a', value: 'A' }, { id: 'b', value: 'B' }, { id: 'c', value: 'C' }, ]) group.select('a') console.log(group.isIndeterminate.value) // true group.selectAll() console.log(group.isIndeterminate.value) // false
selectAll
Type
function selectAll(): voidDetails Selects all selectable (non-disabled) items. Also clears any mixed state on the selected items.
Example
const group = createGroup() group.onboard([ { id: 'a', value: 'A' }, { id: 'b', value: 'B', disabled: true }, { id: 'c', value: 'C' }, ]) group.selectAll() console.log(group.selectedIds.size) // 2 (disabled item excluded) console.log(group.isAllSelected.value) // true
unselectAll
Type
function unselectAll(): voidDetails Clears all selections. When
mandatoryoption is set, keeps one item selected.Example
const group = createGroup() group.onboard([ { id: 'a', value: 'A' }, { id: 'b', value: 'B' }, ]) group.selectAll() group.unselectAll() console.log(group.isNoneSelected.value) // true
toggleAll
Type
function toggleAll(): voidDetails Toggles between all selected and none selected. If all items are currently selected, unselects all. Otherwise, selects all.
Example
const group = createGroup() group.onboard([ { id: 'a', value: 'A' }, { id: 'b', value: 'B' }, ]) group.toggleAll() console.log(group.isAllSelected.value) // true group.toggleAll() console.log(group.isNoneSelected.value) // true