mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-21 14:29:34 +00:00
144 lines
2.6 KiB
Vue
144 lines
2.6 KiB
Vue
<template>
|
|
<div class="wrapper">
|
|
<v-text-field
|
|
:label="label"
|
|
variant="solo"
|
|
v-model="search"
|
|
@keydown.enter="optionSelected()"
|
|
@keydown.tab="optionSelected()"
|
|
:class="{ error: validations?.$errors?.length }"
|
|
:hint="
|
|
validations?.$errors
|
|
? errorUtils.parseErrors(validations?.$errors)
|
|
: null
|
|
"
|
|
/>
|
|
|
|
<div class="suggestion" v-if="suggestion">
|
|
<span class="hidden-part">{{ suggestion._suggestionHiddenPart }}</span>
|
|
<span>{{ suggestion._suggestionShownPart }}</span>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import errorUtils from '@/plugins/lib@auth/_utils/error.utils'
|
|
|
|
export default {
|
|
emits: ['option-selected'],
|
|
|
|
props: {
|
|
label: {
|
|
type: String,
|
|
required: false,
|
|
},
|
|
|
|
options: {
|
|
type: Array,
|
|
required: true
|
|
},
|
|
|
|
validations: {
|
|
type: Object || null,
|
|
required: false
|
|
},
|
|
|
|
clearOnSubmit: {
|
|
type: Boolean,
|
|
required: false,
|
|
default: () => true
|
|
},
|
|
|
|
value: {
|
|
required: false
|
|
}
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
errorUtils,
|
|
search: ''
|
|
}
|
|
},
|
|
|
|
computed: {
|
|
suggestion() {
|
|
const normalizedSearch = this._normalize(this.search)
|
|
|
|
if (!normalizedSearch.length || !this.options.length)
|
|
return null
|
|
|
|
const filteredOptions = this.options.filter(option => {
|
|
const normalizedValue = this._normalize(option.value)
|
|
|
|
return normalizedValue.includes(normalizedSearch)
|
|
// return normalizedSearch == normalizedValue.slice(0, normalizedSearch.length)
|
|
})
|
|
|
|
if (!filteredOptions[0])
|
|
return null
|
|
|
|
// const s = filteredOptions[0].value.split(' ')
|
|
// filteredOptions[0].value = s[1] + ' ' + s[0]
|
|
|
|
const suggestion = {
|
|
...filteredOptions[0],
|
|
_suggestionHiddenPart: filteredOptions[0].value.slice(0, normalizedSearch.length),
|
|
_suggestionShownPart: filteredOptions[0].value.slice(normalizedSearch.length, filteredOptions[0].value.length)
|
|
}
|
|
|
|
return suggestion
|
|
}
|
|
},
|
|
|
|
mounted() {
|
|
if (this.value)
|
|
this.search = this.value
|
|
},
|
|
|
|
methods: {
|
|
optionSelected() {
|
|
if (!this.suggestion)
|
|
return
|
|
|
|
this.$emit('option-selected', this.suggestion)
|
|
|
|
if (this.clearOnSubmit)
|
|
this.search = ''
|
|
else
|
|
this.search = this.suggestion.value
|
|
},
|
|
|
|
_normalize(value) {
|
|
if (!value) return ''
|
|
|
|
return value
|
|
.trim()
|
|
.toLowerCase()
|
|
.normalize("NFD")
|
|
.replace(/[\u0300-\u036f]/g, "")
|
|
}
|
|
},
|
|
|
|
watch: {
|
|
value(value) {
|
|
this.search = value
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="sass" scoped>
|
|
.wrapper
|
|
position: relative
|
|
|
|
.suggestion
|
|
position: absolute
|
|
top: 27px
|
|
left: 15.5px
|
|
opacity: 0.5
|
|
letter-spacing: 0.009375em
|
|
|
|
.hidden-part
|
|
opacity: 0
|
|
</style> |