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

140 lines
3.3 KiB
Vue
Raw Normal View History

<script lang="ts" setup generic="T extends Record<string, unknown>">
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-11-14 17:50:50 +07:00
const model = defineModel<string | string[] | Record<string, unknown> | 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: T[];
refactor: responsive (#180) * refactor: can open one dropdown whe lt.md * style: update MainLayout background color and fix avatar border class name * feat: add touch position binding for dropdown in ProfileMenu * refactor: enhance icon styling in DrawerComponent * fix: update screen size conditions * feat: add responsive search and filter functionality in MainPage * feat: update styling and functionality in BasicInformation and MainPage components * feat: package view mode improve layout and responsiveness * feat: improve layout and responsiveness of ProfileBanner component * feat: enhance TreeView component with improved icon layout and cursor pointer styling * feat: update DialogForm component to prevent text wrapping in the center column * feat: enhance FormDocument, PriceDataComponent, and BasicInfoProduct components with layout and styling improvements * feat: enhance ProfileBanner dark tab * feat: 02 => responsive & responsibleArea type * fix: layout header bg condition & 02 filter col * feat: 04 flow => add AddButton component and enhance layout in FormFlow and FlowDialog * feat: 07 => enhance layout and responsiveness * refactor: simplify header structure and improve layout consistency * fix: improve text color in ItemCard and adjust responsive breakpoints in product service group * refactor: 05 => enhance layout responsiveness and improve class bindings in quotation components * refactor: enhance styling and improve props flexibility in dialog and select components * refactor: 05 => enhance layout responsiveness in quotation components * refactor: 05 => enhance layout responsiveness * refactor: 05 => formWorkerAdd * refactor: 05 => formWorkerAdd Product table * refactor: 05 => improve layout responsiveness and enhance component structure * refactor: enhance grid view handling and improve component imports * refactor: improve column classes for better layout consistency * refactor: 09 => enhance layout structure and improve responsiveness in task order views * refactor: 10 => enhance invoice main page layout and improve component interactions * refactor: 13 => enhance receipt main page layout and improve component interactions * refactor: 11 => enhance layout and improve responsiveness in credit note pages * refactor: 01 => screen.sm search & filter * refactor: 01 => improve layout responsiveness and fix variable naming in branch management forms --------- Co-authored-by: puriphatt <puriphat@frappet.com>
2025-01-27 10:39:53 +07:00
optionLabel?: keyof T | string;
optionValue?: keyof T | string;
placeholder?: string;
hideSelected?: boolean;
readonly?: boolean;
clearable?: boolean;
incremental?: boolean;
fillInput?: boolean;
2024-10-04 09:45:05 +07:00
disable?: boolean;
2024-11-14 17:50:50 +07:00
multiple?: boolean;
hideInput?: boolean;
rules?: ((value: string) => string | true)[];
}>(),
{
option: () => [],
optionLabel: 'label',
optionValue: 'value',
hideSelected: true,
fillInput: true,
2024-10-04 09:45:05 +07:00
disable: false,
},
);
defineEmits<{
(
e: 'filter',
val: string,
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
): void;
}>();
onMounted(() => {
defaultFilter = selectFilterOptionRefMod(
ref(props.option),
options,
typeof props.optionLabel === 'string' ? props.optionLabel : 'label',
);
});
watch(
() => props.option,
() => {
defaultFilter = selectFilterOptionRefMod(
ref(props.option),
options,
typeof props.optionLabel === 'string' ? props.optionLabel : 'label',
);
},
);
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-10-04 09:45:05 +07:00
:disable
:use-input="!hideInput"
2024-09-18 14:29:32 +07:00
emit-value
map-options
2024-11-14 17:50:50 +07:00
:multiple
:use-chips="multiple"
:hide-selected
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"
2024-11-11 13:31:47 +07:00
input-debounce="500"
:option-value="
typeof props.optionValue === 'string' ? props.optionValue : 'value'
"
:option-label="
typeof props.optionLabel === 'string' ? props.optionLabel : 'label'
"
2024-09-18 14:29:32 +07:00
v-model="model"
dense
autocomplete="off"
: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-if="$slots.prepend" v-slot:prepend>
<slot name="prepend"></slot>
</template>
<template v-if="$slots.append" v-slot:append>
<slot name="append"></slot>
</template>
2024-09-18 14:29:32 +07:00
<template v-slot:no-option>
<slot name="no-option"></slot>
2024-09-30 11:37:18 +07:00
<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 || $slots['selected-item']"
v-slot:selected-item="scope"
>
<slot name="selected-item" :scope="scope" :opt="scope.opt as T"></slot>
</template>
<template v-if="$slots.option" v-slot:option="scope">
<slot name="option" :scope="scope" :opt="scope.opt as T"></slot>
</template>
<template v-if="$slots['before-options']" #before-options>
<slot name="before-options"></slot>
</template>
2024-09-18 14:29:32 +07:00
</q-select>
</template>