jws-frontend/src/components/shared/SelectInput.vue

110 lines
2.4 KiB
Vue
Raw Normal View History

2024-09-18 14:29:32 +07:00
<script lang="ts" setup>
import { onMounted, ref, watch } from 'vue';
2024-09-18 14:29:32 +07:00
import { selectFilterOptionRefMod } from 'src/stores/utils';
import { QSelect } from 'quasar';
2024-09-18 14:29:32 +07:00
2024-09-27 15:21:31 +07:00
const model = defineModel<string | null>();
2024-09-18 14:29:32 +07:00
const options = ref<Record<string, unknown>[]>([]);
let defaultFilter: (
value: string,
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
) => void;
const props = withDefaults(
defineProps<{
id?: string;
label?: string;
option: Record<string, unknown>[];
optionLabel?: string;
optionValue?: string;
placeholder?: string;
hideSelected?: boolean;
readonly?: boolean;
clearable?: boolean;
incremental?: boolean;
fillInput?: boolean;
rules?: ((value: string) => string | true)[];
}>(),
{
option: () => [],
optionLabel: 'label',
optionValue: 'value',
hideSelected: true,
fillInput: true,
},
);
defineEmits<{
(e: 'filter', val: string, update: void): void;
}>();
onMounted(() => {
defaultFilter = selectFilterOptionRefMod(
ref(props.option),
options,
props.optionLabel,
);
});
watch(
() => props.option,
() => {
defaultFilter = selectFilterOptionRefMod(
ref(props.option),
options,
props.optionLabel,
);
},
);
2024-09-18 14:29:32 +07:00
</script>
<template>
<q-select
:placeholder="placeholder"
2024-09-18 14:29:32 +07:00
outlined
:clearable
2024-09-18 14:29:32 +07:00
use-input
emit-value
map-options
:hideSelected
2024-09-18 14:29:32 +07:00
hide-bottom-space
:fill-input="fillInput && !!model"
2024-09-18 14:29:32 +07:00
:hide-dropdown-icon="readonly"
input-debounce="0"
:option-value="optionValue"
:option-label="optionLabel"
2024-09-18 14:29:32 +07:00
v-model="model"
dense
:readonly
2024-09-18 14:29:32 +07:00
:label="label"
:options="incremental ? option : options"
:for="`${id}`"
@filter="
(val, update) => {
incremental ? $emit('filter', val, update) : defaultFilter(val, update);
}
"
:rules
2024-09-18 14:29:32 +07:00
>
<template v-slot:no-option>
2024-09-30 11:37:18 +07:00
<slot name="noOption"></slot>
<q-item v-if="!$slots.noOption">
2024-09-18 14:29:32 +07:00
<q-item-section class="text-grey">
{{ $t('general.noData') }}
</q-item-section>
</q-item>
</template>
<template v-if="$slots.selectedItem" v-slot:selected-item="scope">
<slot name="selectedItem" :scope="scope"></slot>
</template>
<template v-if="$slots.option" v-slot:option="scope">
<slot name="option" :scope="scope"></slot>
</template>
2024-09-18 14:29:32 +07:00
</q-select>
</template>