[UI] Added support for custom HTML and data in Autocomplete component.

This commit is contained in:
Fabio Manganiello 2024-09-05 01:19:26 +02:00
parent bbc70fe6e6
commit 3249053eb0
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774

View file

@ -20,12 +20,14 @@
<div <div
class="item" class="item"
:class="{ active: i === curIndex }" :class="{ active: i === curIndex }"
:key="item" :key="getItemText(item)"
:data-item="item" :data-item="getItemText(item)"
v-for="(item, i) in visibleItems" v-for="(item, i) in visibleItems"
@click="onItemSelect(item)"> @click="onItemSelect(item)">
<span class="matching" v-if="value?.length">{{ item.substr(0, value.length) }}</span> <span v-html="item.prefix" v-if="item.prefix"></span>
<span class="normal">{{ item.substr(value?.length || 0) }}</span> <span class="matching" v-if="value?.length">{{ getItemText(item).substr(0, value.length) }}</span>
<span class="normal">{{ getItemText(item).substr(value?.length || 0) }}</span>
<span v-html="item.suffix" v-if="item.suffix"></span>
</div> </div>
</div> </div>
</div> </div>
@ -33,7 +35,6 @@
<script> <script>
export default { export default {
name: "Autocomplete",
emits: ["input"], emits: ["input"],
props: { props: {
items: { items: {
@ -78,6 +79,10 @@ export default {
}, },
computed: { computed: {
itemsText() {
return this.items.map((item) => this.getItemText(item))
},
visibleItems() { visibleItems() {
if (!this.value?.length) if (!this.value?.length)
return this.items return this.items
@ -87,7 +92,7 @@ export default {
return this.showResultsWhenBlank ? this.items : [] return this.showResultsWhenBlank ? this.items : []
return this.items.filter( return this.items.filter(
(item) => item.substr(0, val.length).toUpperCase() === val (item) => this.getItemText(item).substr(0, val.length).toUpperCase() === val
) )
}, },
@ -97,6 +102,10 @@ export default {
}, },
methods: { methods: {
getItemText(item) {
return item.text || item
},
selectNextItem() { selectNextItem() {
this.curIndex++ this.curIndex++
this.normalizeIndex() this.normalizeIndex()
@ -117,7 +126,8 @@ export default {
this.curIndex = this.visibleItems.length - 1 this.curIndex = this.visibleItems.length - 1
// Scroll to the element // Scroll to the element
const el = this.$el.querySelector("[data-item='" + this.visibleItems[this.curIndex] + "']") const curText = this.getItemText(this.visibleItems[this.curIndex])
const el = this.$el.querySelector(`[data-item='${curText}']`)
if (el) if (el)
el.scrollIntoView({ el.scrollIntoView({
block: "start", block: "start",
@ -130,7 +140,7 @@ export default {
if (!this.value) if (!this.value)
return false return false
return this.items.indexOf(this.value) >= 0 return this.itemsText.indexOf(this.value) >= 0
}, },
onFocus() { onFocus() {
@ -144,7 +154,7 @@ export default {
this.visible = false this.visible = false
e.stopPropagation() e.stopPropagation()
this.$emit("input", val) this.$emit("input", val.text || val)
this.curIndex = -1 this.curIndex = -1
this.visible = true this.visible = true
}, },
@ -158,7 +168,7 @@ export default {
}, },
onItemSelect(item) { onItemSelect(item) {
this.$emit("input", item) this.$emit("input", item.text || item)
this.$nextTick(() => { this.$nextTick(() => {
if (this.valueIsInItems()) { if (this.valueIsInItems()) {
this.visible = false this.visible = false