Skip to main content
Vuetify0 is now a release candidate!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

useProxyModel

A composable for syncing refs bidirectionally with selection contexts, enabling seamless v-model integration with selection state.

Usage

The useProxyModel composable syncs an existing ref (like from defineModel()) with a selection context bidirectionally. Changes in either direction automatically propagate.

ts
import { ref } from 'vue'
import { createSelection, useProxyModel } from '@vuetify/v0'

const model = ref<string>()
const selection = createSelection({ events: true })

selection.onboard([
  { id: 'apple', value: 'Apple' },
  { id: 'banana', value: 'Banana' },
])

// Sync model with selection
const stop = useProxyModel(selection, model)

model.value = 'Apple'
console.log(selection.selectedIds) // Set { 'apple' }

selection.select('banana')
console.log(model.value) // 'Banana'

Multiple mode

Pass multiple: true to sync an array model with a multi-select context. This must be explicitmultiple is never inferred from the context:

ts
const model = ref<string[]>([])
const selection = createGroup({ events: true })

selection.onboard([
  { id: 'red', value: 'Red' },
  { id: 'green', value: 'Green' },
  { id: 'blue', value: 'Blue' },
])

const stop = useProxyModel(selection, model, { multiple: true })

selection.toggle('red')
selection.toggle('blue')
console.log(model.value) // ['Red', 'Blue']

The multiple option accepts MaybeRefOrGetter<boolean>, so you can drive it from a prop or computed:

ts
const props = defineProps<{ multiple?: boolean }>()
const stop = useProxyModel(selection, model, { multiple: () => props.multiple ?? false })

Disabled items

When a new item registers with the selection, useProxyModel checks whether the model already holds that item’s value and selects it if so — this is how items that were selected before they mounted get their initial state. The check is skipped if the item is disabled. The disabled property is automatically unwrapped if it is a Ref<boolean>:

ts
selection.onboard([
  { id: 'a', value: 'A' },
  { id: 'b', value: 'B', disabled: ref(true) }, // reactive disabled
])

model.value = 'B'
// 'b' is NOT auto-selected because disabled is true at registration time

Architecture

useProxyModel creates bidirectional sync between v-model refs and selection state:

Proxy Model Flow

Use controls to zoom and pan. Click outside or press Escape to close.

Proxy Model Flow

Reactivity

useProxyModel creates bidirectional reactive sync between a ref and a selection registry. It uses Vue watchers internally for automatic propagation.

BehaviorReactiveNotes
Model → SelectionChanges to model auto-select items
Selection → ModelSelection changes update model
Tip

Automatic cleanup The watchers are disposed automatically via onScopeDispose. The returned stop() function allows early manual cleanup.

Examples

Color Picker

A color swatch selector that wires a plain shallowRef<string> to a createSelection instance via useProxyModel, demonstrating the bidirectional sync the composable provides. The six color swatches are bulk-registered with onboard() and rendered by iterating selection.values() — each ticket carries isSelected and select() so the template never touches the ref directly. A second set of buttons writes to selected from the outside, which useProxyModel detects and calls browse() on the selection to match. The debug panel displays both the ref value and selection.selectedValues simultaneously so you can confirm both sides stay in lock-step regardless of which triggers the change.

Reach for useProxyModel when you need to expose a selection context through a v-model prop — for example, a wrapper component that consumes a parent’s defineModel() while internally using createSelection for multi-item management. The composable returns a stop() function for early cleanup; in a component, Vue’s scope disposal handles this automatically via onScopeDispose. For multi-select v-model sync, pass { multiple: true } and use a ref<string[]> — the single-value path shown here applies to radio-style exclusive choices.

v-model bridge
Ref valueblueSelection valueblueActive labelBlue

FAQ

Discord
Need help? Join our community for support and discussions ↗

API Reference

The following API details are for the useProxyModel composable.
Was this page helpful?

Ctrl+/