Hace algún tiempo, he creado un componente de autocompletar en vue para un proyecto en el que estoy involucrado.
Pero hoy he detectado un pequeño fallo.
Cuando selecciono la opción que quiera con el clic del ratón, la opción no consigue transmitir, como se puede ver en el console.log ()
que se encuentra en el ejemplo. Si hago clic en otra opción de nuevo, lo que aparecerá en console.log ()
la opción seleccionada previamente.
Si pongo una setTimeout( () => {}, 200)
que ya se detecta y emite la opción, pero creo que no es la mejor solución para este caso.
¿Cualquier sugerencia?
ejemplo
const Autocomplete = {
name: autocomplete,
template: #autocomplete,
props: {
items: {
type: Array,
required: false,
default: () => Array(150).fill().map((_, i) => `Fruit ${i+1}`)
},
isAsync: {
type: Boolean,
required: false,
default: false
}
},
data() {
return {
isOpen: false,
results: [],
search: ,
isLoading: false,
arrowCounter: 0
};
},
methods: {
onChange() {
console.log( this.search)
// Let's warn the parent that a change was made
this.$emit(input, this.search);
},
setResult(result, i) {
this.arrowCounter = i;
this.search = result;
this.isOpen = false;
},
showAll() {
this.isOpen = !this.isOpen;
(this.isOpen) ? this.results = this.items : this.results = [];
},
},
computed: {
filterResults() {
// first uncapitalize all the things
this.results = this.items.filter(item => {
return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
});
return this.results;
},
},
watch: {
items: function(val, oldValue) {
// actually compare them
if (val.length !== oldValue.length) {
this.results = val;
this.isLoading = false;
}
}
},
mounted() {
document.addEventListener(click, this.handleClickOutside);
},
destroyed() {
document.removeEventListener(click, this.handleClickOutside);
}
};
new Vue({
el: #app,
name: app,
components: {
autocomplete: Autocomplete
}
});
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
}
.autocomplete {
position: relative;
width: 130px;
}
.autocomplete-results {
padding: 0;
margin: 0;
border: 1px solid #eeeeee;
height: 120px;
overflow: auto;
width: 100%;
}
.autocomplete-result {
list-style: none;
text-align: left;
padding: 4px 2px;
cursor: pointer;
}
.autocomplete-result.is-active,
.autocomplete-result:hover {
background-color: #4aae9b;
color: white;
}
<script src=https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js></script>
<div id=app>
<autocomplete />
</div>
<script type=text/x-template id=autocomplete>
<div class=autocomplete>
<input type=text @blur=onChange v-model=search @click=showAll />
<ul id=autocomplete-results v-show=isOpen ref=scrollContainer class=autocomplete-results>
<li class=loading v-if=isLoading>
Loading results...
</li>
<li ref=options v-else v-for=(result, i) in filterResults :key=i @click=setResult(result, i) class=autocomplete-result :class={ 'is-active': i === arrowCounter }>
{{ result }}
</li>
</ul>
</div>
</script>