En este post te mostraré cómo hacer un autocompletado, autocomplete, auto completado o como le llames usando Bootstrap, Vue y una API.
De modo que al final (por si no sabes lo que es un autocompletado) se cuente con una caja en donde se complete mientras el usuario escribe, así como la búsqueda de Google.
Te mostraré dos ejemplos, uno en donde los resultados se completan localmente, y otro en donde se hace una búsqueda para traer los resultados de la API en tiempo real. Voy a dejar el código completo al final.
Nota: si buscas un autocompletado con JavaScript puro, mira Awesomplete.
Componente para autocompletado
La librería que vamos a usar, y que nos va a proporcionar el autocompletado en un input será vue-bootstrap-typeahead cuyo repositorio está en GitHub.
Lo debemos incluir o instalar con NPM; para este ejemplo yo lo usaré con JavaScript puro y navegador, sin preprocesadores así que lo incluyo con:
<head>
<!-- ... -->
<link href="https://unpkg.com/vue-bootstrap-typeahead/dist/VueBootstrapTypeahead.css" rel="stylesheet">
<script src="https://unpkg.com/vue-bootstrap-typeahead"></script>
<!-- ... -->
</head>
Como te puedes dar cuenta, son dos archivos; uno es el de los estilos y otro es el script. Ambos están disponibles en unpkg.com.
Luego de incluirlo, se debe registrar como componente antes de instanciar tu app de Vue:
Vue.component('vue-bootstrap-typeahead', VueBootstrapTypeahead);
Eso es lo que necesitamos.
Autocompletado con arreglo estático
Este componente para autocompletar se basa simplemente en un arreglo. Veamos su uso más básico en donde autocompleta a partir de un arreglo.
Comenzamos definiendo el autocompletado. Por cierto, recomiendo encerrarlo en un div.
<div>
<vue-bootstrap-typeahead @hit="onNombreSeleccionado"
v-model="busqueda" :data="nombres" placeholder="Busca un nombre" />
</div>
Fíjate en dos cosas. El v-model
tendrá lo que el usuario escriba (puedes usarlo más tarde para detectar que la búsqueda cambió usando watch). Ahora, en data
se define el arreglo de datos para completar, que en este caso está definido dentro de JavaScript.
Presta atención a data,
pues hay que refrescar ese arreglo cuando se quiera autocompletar por búsqueda.
Existe también el evento hit que es cuando el usuario selecciona un elemento de la lista. En este caso estamos invocando al método onNombreSeleccionado
. Veamos ahora el JavaScript:
new Vue({
el: "#app",
data: () => ({
busqueda: "",
nombres: ["Luis Cabrera", "Leon Scott Kennedy", "Claire Redfield", "Noble 6", "Chris Redfield", "Madeline", "Cuphead", "Mugman", "Ori"],
nombreSeleccionado: null,
}),
methods: {
onNombreSeleccionado(nombre) {
this.nombreSeleccionado = nombre;
}
}
});
El método onNombreSeleccionado
se invoca cuando el usuario selecciona un elemento. El primer argumento de la función es el elemento. Ahí puedes hacer lo que tú quieras, en este caso simplemente modifico una propiedad llamada nombreSeleccionado
.
Puedes probar este primer ejemplo en este enlace.
Autocompletar con API
Para este ejemplo utilicé la API de Wikipedia. He comentado el código, y lo he dejado listo para que puedas cambiar la ruta de donde se obtienen los datos.
La función serializer
Antes de empezar quiero mostrarte la función adicional que acepta el autocomplete y se llama serializer
. Esta función sirve para convertir el objeto a cadena y mostrarla amigablemente en la lista; en otras palabras, serializa los resultados.
Si conoces Java entonces este método sería algo como el método toString
. En mi caso como cada artículo de la wikipedia tiene snippet
y title
(entre otros) defino la función así:
serializarValor(articulo) {
return articulo.title + " - " + articulo.snippet;
},
Una vez explicado esto, veamos cómo funciona.
Completando datos cuando el usuario escribe
El algoritmo es sencillo. Escuchamos el evento de cambio de búsqueda, es decir, cuando el valor cambia. En ese momento consultamos la API, traemos los datos y actualizamos el arreglo.
Con los resultados, el autocompletado mostrará lo que coincida y listo. Por cierto, en este caso no estamos esperando a que la API regrese un resultado para permitir otra búsqueda, ni estamos usando debounce pues quise hacer el tutorial lo más simple posible.
Definimos el input para autocompletado, los métodos, etcétera:
<div class="row">
<div class="col-12">
<h1>Autocompletado</h1>
<a href="//parzibyte.me/blog">By Parzibyte</a>
<div>
<vue-bootstrap-typeahead @hit="onArticuloSeleccionado" :serializer="serializarValor" @input="buscarArticulos"
v-model="busqueda" :data="articulos" placeholder="Busca algo en la Wikipedia" />
</div>
<div class="mt-2 alert alert-success">
Artículo seleccionado es:
{{articuloSeleccionado}}
</div>
</div>
</div>
En JavaScript definimos el comportamiento:
Vue.component('vue-bootstrap-typeahead', VueBootstrapTypeahead)
new Vue({
el: "#app",
data: () => ({
busqueda: "",
articulos: [],
articuloSeleccionado: {},
}),
methods: {
// Función que se invoca cuando el texto de búsqueda cambia
async buscarArticulos() {
// La búsqueda como string. La tomamos del campo de texto
const busqueda = this.busqueda;
// Hacemos la petición a nuestra API pasándole la búsqueda. En este caso consulto la wikipedia
const respuesta = await fetch(`https://es.wikipedia.org/w/api.php?action=query&list=search&srprop=snippet&format=json&origin=*&utf8=&srsearch=${busqueda}`);
/**
* Pequeña gran nota: En este caso primero decodifico como texto, luego quito el HTML
* y después hago un JSON.parse así:
let datos = await respuesta.text();
datos = this.quitarHTML(datos);
datos = JSON.parse(datos);
* En tu caso, si tu API no devuelve HTML (como debería ser) simplemente haz un:
const datos = await respuesta.json();
*/
let articulosWikipedia = await respuesta.text();
articulosWikipedia = this.quitarHTML(articulosWikipedia);
articulosWikipedia = JSON.parse(articulosWikipedia);
// Aquí todo depende de la respuesta de tu servidor. Si el mismo solo te da un arreglo, entonces asigna con:
// this.articulos = datos;
//Pero en este caso la API nos regresa un objeto que tiene la propiedad "query" y dentro de la misma tiene la propiedad search
this.articulos = articulosWikipedia.query.search;
},
quitarHTML(html) {
return html.replace(/<\/?[^>]+>/gi, '');
},
// Función que convierte el objeto a cadena. Es llamado para mostrarse en la lista
serializarValor(articulo) {
return articulo.title + " - " + articulo.snippet;
},
onArticuloSeleccionado(articulo) {
this.articuloSeleccionado = articulo;
}
}
});
Espero que los comentarios sean suficientes, y si no, ahí está la caja de comentarios. Al probarla se ve así:
De este modo estamos autocompletando resultados a partir de una API que se comunica a través de JSON. Obviamente esta API puede estar programada en cualquier lenguaje de tu elección, o igualmente puedes usar una API pública.
Puedes probar el ejemplo aquí.
Conclusión
He colocado el código de estos dos ejemplos en mi GitHub; si quieres dales un vistazo. Te invito a leer más sobre:
Nos leemos después.