Background:
I was trying to do some custom styling for my select element by changing the color and arrow example:
<select :id="'select' + index" class="w-full px-4 py-2 pr-8 bg-theme text-white rounded-md hover:bg-theme/50 appearance-none" @focus="dropdownOpen = true" @blur="dropdownOpen = false">
<option value="">Select</option>
<option v-for="subject in subjects" :key="subject" :value="subject">{{ subject }}</option>
</select>
<span class="absolute right-2 top-1/2 transform -translate-y-1/2 text-white cursor-default" @click.stop="toggleDropdown(index)">
▼
</span>
const dropdownOpen = ref(false)
const toggleDropdown = (index: number) => {
dropdownOpen.value = !dropdownOpen.value;
if (dropdownOpen.value && document.getElementById(`select${index}`)) {
const evt = new MouseEvent('click')
document.getElementById(`select${index}`)?.dispatchEvent(evt)
}
}
Problem:
Currently when trying to expand the select option from another element not working out. You can see on the snippet below itself.
function expand() {
const evt = new MouseEvent('focus')
const el = document.getElementById(`selectbox`);
el.dispatchEvent(evt)
}
<select id="selectbox">
<option id="option1">A</option>
<option id="option2">B</option>
<option id="option3">C</option>
</select>
<button id='test' onclick="expand()">abc</button>
How can we expand select element from another element?
With Vue, there is very rarely a need to ever use the Document API (e.g. using getElementById). You should use a template ref instead.
<!-- id no longer needed -->
<select
ref="select"
class="w-full px-4 py-2 pr-8 bg-theme text-white rounded-md hover:bg-theme/50 appearance-none"
@focus="dropdownOpen = true"
@blur="dropdownOpen = false"
>
const select = useTemplateRef('select')
I assume the select is inside a v-for loop, since you're using index
value. When using a template ref inside of a v-for, the template ref will become an array in order to hold the multiple references created inside the loop. Calling the showPicker function is then as easy as:
const toggleDropdown = (index: number) => {
select.value[index].showPicker()
}