Vue 3: Deselect All Options in Multiple Selects
Learn how to programmatically deselect all options across multiple Vue 3 select elements on button click using v-model reactivity, template refs, or form reset. Pure Vue 3 solutions without jQuery for efficient form resets.
Vue 3: How to programmatically deselect all selected options across multiple select elements in a form on button click?
I have a form with several <select> inputs and need to unselect all currently selected options when a button is clicked, similar to jQuery’s $("option:selected").removeAttr("selected");.
Current code:
<template>
<form id="myform">
<select @change="clearOptions($event)" id="mySelect">
<option>Pineapple</option>
<option>Banana</option>
</select>
<select @change="clearOptions($event)" id="mySelectTwo">
<option>Apple</option>
<option>Orange</option>
</select>
</form>
</template>
<script setup>
const clearOptions = (e) => {
e.preventDefault();
// Need pure Vue 3 solution to deselect all options without jQuery
};
</script>
What is the recommended Vue 3 way (using reactivity, refs, or DOM manipulation) to achieve this?
In Vue 3, the cleanest way to programmatically deselect all selected options across multiple select elements in a form on button click is through reactive v-model bindings—set each vue 3 select’s value to null or an empty string via refs. This beats jQuery’s removeAttr("selected") by leveraging Vue 3 reactivity for instant UI updates without DOM hacks. Add a reset button that loops through your model refs, and you’re done—no @change misuse needed.
Contents
- Understanding Vue 3 Select Reset
- Method 1: Reactive Reset with v-model
- Method 2: Template Refs and DOM Manipulation
- Method 3: Form-Wide Reset with Native API
- Handling Multiple Selects and Edge Cases
- Best Practices and Common Pitfalls
- Sources
- Conclusion
Understanding Vue 3 Select Reset
Ever clicked a reset button in a form and watched selections stubbornly hang on? That’s the pain your current code hits—@change on selects won’t trigger from a button, and jQuery feels like a relic in Vue 3. The fix? Vue’s reactivity system shines here. Native HTML select elements ignore selected attributes once Vue mounts (it prioritizes v-model), so you control them via JavaScript refs or bindings.
Why multiple methods? Reactive v-model is declarative and scales effortlessly for vue 3 reset form scenarios. Refs offer direct DOM control for edge cases, like when you skip v-model. And form-level resets handle bulk ops natively. Pick based on your setup: if you’re already modeling form data (smart move), go reactive. Otherwise, refs get gritty but work.
Your code’s close—just swap @change for a button’s @click, bind models, and reset. Let’s build it step by step.
Method 1: Reactive Reset with v-model
This is the Vue 3 way: bind each vue 3 select to a reactive ref, then null them out on click. It’s reactive, so the DOM updates instantly—no manual option fiddling.
Start with refs for your values. For single selects, use ref(null) or ref(''). Add a placeholder option like <option value="">Select...</option> to show “cleared” visually.
Here’s your form, refactored:
<template>
<form id="myform">
<select v-model="select1" id="mySelect">
<option value="">Select fruit</option>
<option value="pineapple">Pineapple</option>
<option value="banana">Banana</option>
</select>
<select v-model="select2" id="mySelectTwo">
<option value="">Select fruit</option>
<option value="apple">Apple</option>
<option value="orange">Orange</option>
</select>
<button type="button" @click="resetForm">Reset All</button>
</form>
</template>
<script setup>
import { ref } from 'vue'
const select1 = ref(null)
const select2 = ref(null)
const resetForm = () => {
select1.value = null
select2.value = null
}
</script>
Boom—click resets both. Why null over ''? Matches non-string values perfectly; use '' if your options are strings. As the Vue.js Forms documentation notes, “For unbound selects, Vue ignores the selected attribute and treats it as unselected.”
Scale to more? Object of refs:
const formData = ref({
select1: null,
select2: null
})
const resetForm = () => {
Object.keys(formData.value).forEach(key => {
formData.value[key] = null
})
}
No watchers needed. Reactive magic.
Method 2: Template Refs and DOM Manipulation
Skip v-model? Use template refs for direct access, then selectedIndex = -1 on each element. Perfect for vue 3 programmatically clear select without models, or legacy forms.
Ref an array for multiples: ref="selects". Vue collects them automatically.
Updated template:
<template>
<form id="myform">
<select ref="selects" id="mySelect">
<option>Pineapple</option>
<option selected>Banana</option> <!-- Vue ignores this -->
</select>
<select ref="selects" id="mySelectTwo">
<option>Apple</option>
<option selected>Orange</option>
</select>
<button type="button" @click="resetSelects">Reset All</button>
</form>
</template>
<script setup>
import { ref, nextTick } from 'vue'
const selects = ref([])
const resetSelects = async () => {
await nextTick() // Ensures DOM ready
selects.value.forEach(select => {
select.selectedIndex = -1
})
}
</script>
selectedIndex = -1 deselects everything—works for single or multi-selects, per MDN’s HTMLSelectElement docs. Why nextTick? Button clicks can race DOM updates.
This mirrors your jQuery intent but Vue-native. Tradeoff: less reactive than v-model (no auto-tracking changes).
Method 3: Form-Wide Reset with Native API
For vue 3 form reset button across dozens of inputs? Grab the form ref and call reset(). It reverts to initial value attrs—but selects need careful setup.
Template tweak:
<template>
<form ref="formRef" id="myform">
<select id="mySelect">
<option value="">--</option> <!-- Initial empty -->
<option value="pineapple">Pineapple</option>
<option value="banana">Banana</option>
</select>
<!-- Same for mySelectTwo -->
<button type="button" @click="resetFormNative">Reset</button>
</form>
</template>
<script setup>
import { ref } from 'vue'
const formRef = ref(null)
const resetFormNative = () => {
formRef.value.reset()
}
</script>
Simple! But requires empty initial options. Combine with v-model for hybrid power. The Vue template refs guide backs this for bulk DOM ops.
Quick comparison:
| Method | Pros | Cons | Best For |
|---|---|---|---|
| v-model | Reactive, declarative, tracks values | Needs per-select refs | Modeled forms |
| Template Refs | Direct control, no models | Imperative, nextTick boilerplate |
Quick DOM tweaks |
| Form Reset | Zero loops, native | Relies on HTML defaults | Simple forms |
Handling Multiple Selects and Edge Cases
What about <select multiple>? v-model uses arrays: ref([]), reset to [].
const multiSelect = ref([])
const resetMulti = () => { multiSelect.value = [] }
Dynamic forms? Watch selects.value.length or use computed. Button outside form? No issue—refs are global.
Edge cases bite: Async options loading? Reset post-load with onMounted + nextTick. Multi-select partial clears? Loop options and set selected = false, but selectedIndex = -1 handles it.
From community fixes like this Stack Overflow thread, watchers help dynamic resets:
import { watch } from 'vue'
watch(() => someCondition.value, () => {
select1.value = null
})
Your @change? Ditch it—buttons use @click.
Best Practices and Common Pitfalls
Favor v-model—it’s Vue 3’s heart. Avoid option loops; null/ selectedIndex=-1 is faster. Pitfall: No placeholder? Reset looks “selected” (empty option stays). Fix: Always add <option value="">.
Vue 2 vs 3? Options API used $refs; Composition API refs are cleaner. Third-party like vue-multiselect? Overkill—stick native for vue 3 clear select options.
Test: Mount, select, click. No change? Console select.value—timing issue, add nextTick. Mobile? Selects behave identically.
Pro tip: Expose reset via composable for reusability.
// composables/useFormReset.js
import { ref, nextTick } from 'vue'
export function useFormReset(selects) {
const reset = async () => {
await nextTick()
selects.value.forEach(s => s.selectedIndex = -1)
}
return { reset }
}
Here’s where it gets flexible.
Sources
- Vue.js Forms — Official guide on v-model for selects and form resets: https://vuejs.org/guide/essentials/forms.html
- Vue.js Template Refs — Documentation for accessing DOM elements like select refs: https://vuejs.org/guide/essentials/template-refs.html
- MDN HTMLSelectElement.selectedIndex — Native API for deselecting options programmatically: https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/selectedIndex
- Stack Overflow: Reset Select in Vue.js — Community solutions for v-model null resets: https://stackoverflow.com/questions/52114570/how-to-reset-select-drop-down-in-vuejs
- Stack Overflow: Clear v-model on Select Change — Handling dynamic clears with watchers: https://stackoverflow.com/questions/51530477/how-to-clear-v-model-used-with-a-select-when-options-change
Conclusion
Vue 3 makes vue 3 deselect all options trivial—v-model refs win for reactivity, refs/DOM for control, form reset for simplicity. Ditch jQuery; your form now resets smoothly on any button click. Scale it, test edges, and forms feel alive. Grab the code, tweak, deploy.