I tried to follow this guide but I think the quasar API has changed so much that it doesn’t work anymore.
I managed to make a wrapped q-select that works and might be helpful if you are wrapping quasar (or Vue) components
I wanted a q-select that would have basic filtering enabled. e.g. It could replace q-select and not have to setup extra code for filtering.
<ex-select v-model.number="product.supplierId" label="Supplier"
:options="supplierListSorted"
option-value="supplierId"
option-label="companyName"
emit-value map-options
filled />
Vue components can use v-bind="$attrs" to bind any attributes that do not match the component params e.g. if you use <ex-select filled … then the filled attribute will be passed down to the component automatically.
The same applies for v-on="$listeners" where any event handlers will be passed down to the component. v-model binds the input event so this is why it works without any extra code.
The props “options”, “optionValue” and “optionLabel” are declared because I want to use them in the component code. So if you need to work with an attribute then you need to declare it and add it manually to the wrapped component.
There is code to work with lists that have a key value and display value e.g. supplierId and supplierName. If optionLabel is set, then filter on that property on the object. Otherwise assume the array just contains string values and filter directly.
Here is the full ExSelect.vue code
<template>
<q-select
v-bind="$attrs"
use-input
fill-input
hide-selected
input-debounce="0"
:options="selectOptions"
:option-label="optionLabel"
:option-value="optionValue"
v-on="$listeners"
@filter="handleFilter">
<template v-slot:no-option>
<q-item>
<q-item-section class="text-grey">
No results
</q-item-section>
</q-item>
</template>
</q-select>
</template>
<script>
export default {
name: "ExSelect",
// eslint-disable-next-line
props: ["options", "optionValue", "optionLabel"],
data() {
return {
selectOptions: null
};
},
updated() {
if (!this.selectOptions) {
console.log("[ExSelect] updated options is ", this.options);
// keep a copy of the original options list
this.selectOptions = this.options.slice();
}
},
methods: {
handleFilter(value, doneFunc) {
console.log("[ExSelect] handleFilter", value);
if (value === "") {
doneFunc(() => {
// reset the list
console.log("[ExSelect] handleFilter reset list", value);
this.selectOptions = this.options.slice();
});
return;
}
doneFunc(() => {
const input = value.toLowerCase();
console.log("[ExSelect] handleFilter filtering", value);
this.selectOptions = this.options.filter((item) => {
if (this.optionLabel) { // search the display property
return item[this.optionLabel].toLowerCase().indexOf(input) > -1;
}
return item.toLowerCase().indexOf(input) > -1;
});
});
}
}
};
</script>
I’m still learning Vue so there are probably better ways to do some things but might help out someone trying to do a similar thing.