nuVistA/htdocs/Autocomplete.vue

110 lines
2.5 KiB
Vue
Raw Normal View History

2022-09-22 07:10:08 -04:00
<template>
2023-04-24 21:30:14 -04:00
<div class="dropdown" :class="{ 'form-floating': label }">
<input type="text" class="form-control" placeholder=" " @focus="option_open" @input="option_filter" v-model="x_modelValue" @keydown.down="option_down" @keydown.up="option_up" @keydown.enter="option_enter" />
<ul class="dropdown-menu shadow" :class="{ show: (open) && (results.length > 0) }">
2022-09-22 07:10:08 -04:00
<li class="loading" v-if="!items">Loading results...</li>
2023-04-24 21:30:14 -04:00
<li v-else v-for="(result, i) in results" :key="i" @click="option_click(result)" class="dropdown-item" :class="{ 'is-active': i === index }">{{ result }}</li>
2022-09-22 07:10:08 -04:00
</ul>
2023-04-24 21:30:14 -04:00
<label v-if="label">{{label}}</label>
2022-09-22 07:10:08 -04:00
</div>
</template>
<style scoped>
2023-04-24 21:30:14 -04:00
.dropdown-menu {
width: 100%;
max-height: 10rem;
2022-09-22 07:10:08 -04:00
overflow: auto;
}
2023-04-24 21:30:14 -04:00
.dropdown-item {
cursor: default;
2022-09-22 07:10:08 -04:00
}
2023-04-24 21:30:14 -04:00
.dropdown-item.is-active,
.dropdown-item:hover {
background-color: var(--bs-primary);
color: var(--bs-body-bg);
2022-09-22 07:10:08 -04:00
}
</style>
<script>
export default {
props: {
2023-04-24 21:30:14 -04:00
modelValue: {
2022-09-22 07:10:08 -04:00
type: String,
default: ''
},
items: {
type: Array,
required: false,
default: () => [],
2023-04-24 21:30:14 -04:00
},
label: String
2022-09-22 07:10:08 -04:00
},
2023-04-24 21:30:14 -04:00
emits: [
'update:modelValue'
],
2022-09-22 07:10:08 -04:00
data() {
return {
2023-04-24 21:30:14 -04:00
x_modelValue: this.modelValue,
2022-09-22 07:10:08 -04:00
results: [],
open: false,
index: -1,
};
},
watch: {
2023-04-24 21:30:14 -04:00
modelValue(val) {
this.x_modelValue = val;
2022-09-22 07:10:08 -04:00
},
2023-04-24 21:30:14 -04:00
x_modelValue(val) {
this.$emit('update:modelValue', val);
2022-09-22 07:10:08 -04:00
}
},
mounted() {
2023-04-24 21:30:14 -04:00
this.x_modelValue = this.modelValue;
2022-09-22 07:10:08 -04:00
document.addEventListener('click', this.option_close)
},
destroyed() {
document.removeEventListener('click', this.option_close)
},
methods: {
option_open() {
if(this.items) {
2023-04-24 21:30:14 -04:00
this.results = this.items;
this.open = true;
}
},
option_filter() {
if(this.items) {
if(this.x_modelValue) {
var selection = this.x_modelValue.toLowerCase();
this.results = this.items.filter((item) => item.toLowerCase().indexOf(selection) >= 0);
} else this.results = this.items;
2022-09-22 07:10:08 -04:00
this.open = true;
}
},
option_down() {
if(this.index < this.results.length) this.index++;
},
option_up() {
if(this.index > 0) this.index--;
},
option_enter() {
2023-04-24 21:30:14 -04:00
this.x_modelValue = this.results[this.index];
2022-09-22 07:10:08 -04:00
this.open = false;
this.index = -1;
},
option_click(result) {
2023-04-24 21:30:14 -04:00
this.x_modelValue = result;
2022-09-22 07:10:08 -04:00
this.open = false;
},
option_close(evt) {
if(!this.$el.contains(evt.target)) {
this.open = false;
this.index = -1;
}
}
}
};
</script>