Files
app/src/components/inputs/ComboboxInput.vue
T
2023-08-23 21:40:32 +02:00

120 lines
2.6 KiB
Vue

<script setup>
import {ref, watch} from "vue";
const props = defineProps({
modelValue: {
type: [Object, Array]
},
rules: {
type: Array,
required: false,
default: () => []
},
enableNewValues: {
type: Boolean,
required: false,
default: true,
},
options: {
type: Array,
required: true,
},
optionLabel: {
type: String,
required: false,
default: "name"
},
optionValue: {
type: String,
required: false,
default: "id"
}
})
const model = ref({});
watch(() => props.modelValue, (newVal) => {
model.value = newVal;
}, {immediate: true});
const emit = defineEmits(['update:modelValue', 'clear']);
watch(model, (val) => {
if (!val) return;
let value = val;
if (typeof val === 'string') value = {name: val};
if (value['__typename']) {
delete value['__typename'];
}
emit("update:modelValue", value);
})
const clearValue = () => {
model.value = {};
emit("clear");
}
const inputValue = ref("");
const inputValueChanged = (value) => {
if (model.value?.name && value !== '') {
// reset model
delete model.value.id;
model.value.name = '';
}
inputValue.value = value;
}
const handleOnBlur = () => {
if (inputValue.value !== '') {
model.value = inputValue.value;
inputValue.value = "";
}
}
let availableOptions = ref([]);
const filterFn = (val, update, abort) => {
update(() => {
if (!val || val === "") {
availableOptions.value = props.options;
} else {
const needle = val.toLowerCase();
availableOptions.value = props.options.filter(v => {
return v.name.toLowerCase().indexOf(needle) > -1;
});
}
availableOptions.value = availableOptions.value.map(i => ({id: i.id, name: i.name}))
})
}
</script>
<template>
<q-select
v-model="model"
use-input
input-debounce="100"
:display-value="`${model ? model[optionLabel] : ''}`"
:rules="rules"
@filter="filterFn"
@input-value="inputValueChanged"
@blur="handleOnBlur"
@clear="clearValue"
:options="availableOptions"
:option-label="optionLabel"
:option-value="optionValue"
:new-value-mode="enableNewValues ? 'add' : 'toggle'"
clear-icon="clear"
:v-bind="$attrs"
>
<template v-slot:no-option v-if="enableNewValues">
<q-item v-if="inputValue">
<q-item-section avatar>
<q-avatar text-color="green" size="32px" icon="add"/>
</q-item-section>
<q-item-section class="text-grey">
<span>Vytvořit novou hodnotu <q-chip>{{ inputValue }}</q-chip></span>
</q-item-section>
</q-item>
</template>
</q-select>
</template>