import { QSelect } from 'quasar'; import { Ref, watch } from 'vue'; export type SelectProps any> = { params?: Parameters[0]; creatable?: boolean; creatableDisabled?: boolean; creatableDisabledText?: string; label?: string; placeholder?: string; readonly?: boolean; required?: boolean; disabled?: boolean; clearable?: boolean; autoSelectOnSingle?: boolean; }; export const createSelect = >( state: { value: Ref; valueOption: Ref; selectOptions: Ref; getByValue: (id: string) => Promise | T | void; getList: (query?: string) => Promise | T[] | void; }, opts?: { valueField?: keyof T; }, ) => { const { value, valueOption, selectOptions, getList, getByValue } = state; const valueField = opts?.valueField || 'value'; let cache: T[]; let previousSearch = ''; watch(value, (v) => { if (!v || (cache && cache.find((opt) => opt[valueField] === v))) return; getSelectedOption(); }); async function getOptions(query?: string) { if (cache && selectOptions.value.length > 0 && previousSearch === query) { selectOptions.value = JSON.parse(JSON.stringify(cache)); return; } const ret = await getList(query); if (ret) { cache = ret; selectOptions.value = JSON.parse(JSON.stringify(cache)); previousSearch = query || previousSearch; } getSelectedOption(); } async function setFirstValue() { if (value.value) return; const first = selectOptions.value.at(0); if (first) value.value = first[valueField]; } async function getSelectedOption() { const currentValue = value.value; if (!currentValue) return; if (selectOptions.value.find((v) => v[valueField] === currentValue)) return; if (valueOption.value && valueOption.value[valueField] === currentValue) { return selectOptions.value.unshift(valueOption.value); } const ret = await getByValue(currentValue); if (ret) { selectOptions.value.unshift(ret); valueOption.value = ret; } } type QuasarSelectUpdate = ( callback: () => void, afterFn?: ((ref: QSelect) => void) | undefined, ) => void; function filter(value: string, update: QuasarSelectUpdate) { update( () => getOptions(value), (ref) => { if (!!value && ref.options && ref.options.length > 0) { ref.setOptionIndex(-1); ref.moveOptionSelection(1, true); } }, ); } return { getOptions, setFirstValue, getSelectedOption, filter }; };