I have a ref on a dropdown component called 'dropdown'
when an item is selected, I want to get the selected label(I can get the value, but its different than the label)
when I do dropdown.value I get an object where I can see the key with its value I want within it, which is 'selectedLabel'
if I do dropdown.value.selectedLabel I get blank and dropdown.value.selectedLabel.value is undefined.
<template>
<div class="dropdown-component">
<div class="label">{{name}}</div>
<div class="select-container">
<el-select
ref="dropdown"
v-model="selectedValue"
filterable
@change="$emit('OPTION_SELECTED', selectedOptionData())"
:placeholder="placeholderText"
>
<el-option
v-for="(item,index) in options"
:key="index"
:label="getLabel(item)"
:value="getValue(item)"
>
</el-option>
</el-select>
</div>
</div>
</template>
<script>
import { ref, defineComponent, watchEffect, computed } from 'vue'
import { getAPIObjFor } from '@/lib/ymm/YMMApi'
export default defineComponent({
props: {
labelKey: String,
valueKey: { type: String, default: '' },
name: String,
next: String,
groupState: Object
},
emits: ['OPTION_SELECTED'],
setup (props) {
console.log('Initing Dropdown-', props.name)
const options = ref([])
const selectedValue = ref('')
const activeQueryParam = ref('')
const dropdown = ref(null)
const apiQueryObj = getAPIObjFor(props.name)
const getOptionData = async ({ apiQuery, apiRequest }) => {
// keep log
console.log('%c' props.name ' query:', 'color:orange', apiQuery)
activeQueryParam.value = apiQuery
options.value = await apiRequest(apiQuery)
}
const getLabel = (_item) => {
return _item[props.labelKey]
}
const getValue = (_item) => {
const valueKey = props.valueKey === '' ? props.labelKey : props.valueKey
return { value: _item[valueKey], label: getLabel(_item), x: 'x' }
}
const selectedOptionData = () => {
// eslint-disable-next-line dot-notation
// eslint-disable-next-line vue/no-ref-as-operand
// eslint-disable-next-line
console.log('selected dropdown', dropdown.value, dropdown.value.clearIcon, dropdown.value.selectedLabel)
const { name } = props
const { value, label } = selectedValue.value
const selectedData = {
[`${name}`]: {
value,
label,
next: props.next
}
}
return selectedData
}
const placeholderText = computed(() => {
return `Select a ${props.name}`
})
watchEffect(() => {
const query = apiQueryObj(props.groupState)
if (query && query.apiQuery !== activeQueryParam.value) {
selectedValue.value = ''
getOptionData(query)
}
})
return { options, getValue, getLabel, selectedValue, selectedOptionData, placeholderText, dropdown }
}
})
</script>
<style lang="scss" scoped>
.dropdown-component {
max-width: 500px;
display: flex;
flex-direction: row;
justify-content: space-between;
.select-container {
max-width: 400px;
display: flex;
min-width: 20px;
flex-grow: 1;
}
.el-select {
width: 100%;
}
}
</style>
CodePudding user response:
You can use el-select
's selected
property instead of selectedLabel
, which always seems to be blank for some reason.
The selected
property contains an array of selected options (each containing a currentLabel
property), where the last array element is the most recently selected. However, the selected
property is updated after the change
event, so you have to await the next tick before accessing it.
import { nextTick } from 'vue'
//...
const selectedOptionData = async () => {
await nextTick()
const selected = dropdown.value.selected.at(-1).currentLabel
console.log('selectedLabel', selected)
//...
}
Also your @change
event handler would have to be modified to be async for this to work:
<el-select @change="onChange">
export default {
setup(props, { emit }) {
const onChange = async () => {
emit('OPTION_SELECTED', await selectedOptionData())
}
return { onChange }
}
}
Just be aware that the change
-event also occurs when a tag is removed.