149 lines
3.8 KiB
Vue
149 lines
3.8 KiB
Vue
<template lang="pug">
|
|
|
|
div.modal.fade(
|
|
:id="modalId"
|
|
tabindex="-1"
|
|
aria-labelledby="addEmployeeModalLabel"
|
|
aria-hidden="true"
|
|
data-bs-focus="true"
|
|
)
|
|
.modal-dialog
|
|
.modal-content
|
|
.modal-header
|
|
h5.modal-title#addEmployeeModalLabel Mitarbeiter hinzufügen
|
|
button.btn-close(
|
|
type="button"
|
|
aria-label="Close"
|
|
data-bs-dismiss="modal"
|
|
)
|
|
.modal-body
|
|
input.form-control#inputAutocomplete(
|
|
v-model="query"
|
|
@input="onChange($event)"
|
|
@keypress.enter="onEnter"
|
|
@keypress.down="onDown"
|
|
@keypress.up="onUp"
|
|
)
|
|
.card.p-0(v-show="isOpenSuggestions")
|
|
ul.list-group.text-start
|
|
li.dropdown-item(
|
|
v-for="(sugg, i) in suggestions"
|
|
:key="i"
|
|
@click="setResult(sugg)"
|
|
:class="{'active' : selected === i}"
|
|
) {{sugg.name}}
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { Modal } from 'bootstrap'
|
|
import { computed, ref, onMounted } from 'vue'
|
|
import type { Ref } from 'vue'
|
|
|
|
/**
|
|
* Begin definitions
|
|
*/
|
|
const props = defineProps<{
|
|
modalId: string,
|
|
searchData : [],
|
|
searchFields? : string[],
|
|
sourceRow? : number,
|
|
minQueryLength? : number
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'emitResult', result : Employee) : Employee
|
|
}>()
|
|
|
|
const query : Ref<string> = ref('')
|
|
const isOpenSuggestions : Ref<boolean> = ref(false)
|
|
const suggestions : Ref<Employee[]> = ref([])
|
|
const result : Ref<Employee | undefined> = ref()
|
|
const selected : Ref<number> = ref(0)
|
|
|
|
/**
|
|
* End definitions
|
|
*
|
|
*
|
|
*
|
|
* Begin functions
|
|
*/
|
|
function filterResults(query : string) {
|
|
suggestions.value = props.searchData.filter((el: { name: string }) => {
|
|
return el.name.toLowerCase().search(query.toLowerCase()) > -1
|
|
})
|
|
}
|
|
|
|
function setResult(pResult : Employee) {
|
|
result.value = pResult
|
|
query.value = pResult.name
|
|
isOpenSuggestions.value = false
|
|
emit('emitResult', result.value)
|
|
}
|
|
|
|
/**
|
|
* End Functions
|
|
*
|
|
*
|
|
* Begin Event listeners
|
|
*/
|
|
function onChange(event : Event){
|
|
let query : string = (<HTMLInputElement>event?.target).value
|
|
|
|
if(query.length >= (props.minQueryLength ?? 1)) {
|
|
filterResults(query)
|
|
isOpenSuggestions.value = true
|
|
}
|
|
else {
|
|
isOpenSuggestions.value = false
|
|
}
|
|
}
|
|
|
|
function onModalHide() {
|
|
query.value = ''
|
|
result.value = undefined
|
|
suggestions.value = []
|
|
isOpenSuggestions.value = false
|
|
}
|
|
|
|
function onEnter() {
|
|
if(selected.value > -1 && selected.value < suggestions.value.length ) {
|
|
setResult(suggestions.value[selected.value])
|
|
}
|
|
}
|
|
|
|
function onDown() {
|
|
if (selected.value < suggestions.value.length - 1) {
|
|
selected.value++
|
|
}
|
|
}
|
|
function onUp() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Lifecycle Hooks
|
|
*/
|
|
onMounted(() => {
|
|
let modal = document.getElementById(props.modalId);
|
|
|
|
modal?.addEventListener('hide.bs.modal', onModalHide)
|
|
|
|
modal?.addEventListener('shown.bs.modal', () => {
|
|
document.getElementById('inputAutocomplete')?.focus()
|
|
})
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
|
|
li.dropdown-item:active,
|
|
li.dropdown-item.active {
|
|
background-color: #e9ecef;
|
|
color: #1e2125;
|
|
}
|
|
|
|
li.dropdown-item {
|
|
cursor: pointer;
|
|
}
|
|
|
|
</style> |