Skip to content

Instantly share code, notes, and snippets.

@CristalT
Created August 28, 2019 14:54
Show Gist options
  • Save CristalT/5315ab8312df94189446d8ffa17d9273 to your computer and use it in GitHub Desktop.
Save CristalT/5315ab8312df94189446d8ffa17d9273 to your computer and use it in GitHub Desktop.
## Componente Autocomplete para Vuejs. Reemplaza el Datalist HTML5 que presenta algunos problemas entre navegadores. ### Propiedades - input-class: clase css que se aplica al input text donde se realiza la búsqueda - placeholder: texto de campo vac
<template>
<div>
<div v-if="!loading">
<input
type="text"
:class="inputClass"
:placeholder="placeholder"
v-model="terms"
@focus="resetStatus"
@keydown.down="onArrowDown"
@keydown.up="onArrowUp"
@keydown.enter="onEnter"
/>
<div v-if="isVisible" class="autocomplete__results">
<ul>
<li
v-for="(item, index) in results"
:key="index"
@click="setValue(item)"
:class="{ 'is-active': index === arrowCounter }"
@mouseover="arrowCounter = index"
>{{ item[text] }}</li>
</ul>
</div>
</div>
<span v-else class="loading__caption">{{ loadingCaption }}</span>
</div>
</template>
<script>
export default {
props: {
inputClass: {
type: String
},
placeholder: {
type: String
},
text: {
type: String,
default: 'text'
},
value: {
type: String,
default: 'value'
},
data: {
type: Array
},
minLength: {
type: Number | String,
default: 3
},
loading: {
type: Boolean,
default: false
},
loadingCaption: {
type: String,
default: 'Cargando ...'
}
},
data() {
return {
terms: '',
itemSelected: false,
arrowCounter: -1
};
},
computed: {
isVisible() {
return this.results.length && !this.itemSelected;
},
results() {
const terms = this.terms;
if (terms.length >= this.minLength) {
const words = terms.split(' ');
const all = this.data.filter(item =>
words.every(
w => item[this.text].toLowerCase().indexOf(w.toLowerCase()) > -1
)
);
return all.slice(0, 5);
}
return [];
}
},
methods: {
onArrowDown() {
if (this.arrowCounter < this.results.length) {
this.arrowCounter = this.arrowCounter + 1;
}
},
onArrowUp() {
if (this.arrowCounter > 0) {
this.arrowCounter = this.arrowCounter - 1;
}
},
onEnter() {
const item = this.results[this.arrowCounter]
this.setValue(item)
},
setValue(item) {
this.terms = item[this.text];
this.itemSelected = true;
this.arrowCounter = -1
this.$emit('selected', item);
},
resetStatus(e) {
e.target.select();
this.itemSelected = false;
}
}
};
</script>
<style scoped>
.autocomplete__results {
position: absolute;
width: 95%;
background-color: #fff;
z-index: 9;
border: 1px solid #eee;
}
.autocomplete__results ul {
margin: 0;
list-style: none;
padding: 0;
}
.autocomplete__results ul li {
padding: 3px 10px;
cursor: pointer;
font-size: 12px;
}
.autocomplete__results ul li.is-active {
background-color: #4aaeb9;
color: white;
}
.loading__caption {
font-size: 12px;
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment