Skip to content

useSearchBar

Este composable permite implementar funcionalidad de búsqueda en tiempo real sobre un array de elementos.

export function useSearchBar<Item>(
itemsArray: Item[], // Lista original de elementos a filtrar
pageLocale?: { searchTitle: string }, // (opcional) Locales de la pagina para sacar el texto que quieran mostrar.
key: keyof Item = "name" as keyof Item // Nombre del atributo del objeto de la lista que tiene que comparar. (de tipo String)
) {
/**
* Estado reactivo que almacena el texto actual del filtro de búsqueda
*/
const nameFilter = ref("");
/**
* Lista filtrada de elementos que coinciden con el criterio de búsqueda
*/
const searchedItems = computed(() =>
itemsArray.filter((item) =>
compareNormalizedText(String(item[key]), nameFilter.value)
)
);
/**
* Función para actualizar el filtro de búsqueda
* @param filter - Texto del filtro a aplicar
*/
const filterProvider = (filter: string) => {
nameFilter.value = filter;
};
/**
* Título dinámico para la página que incluye el término de búsqueda
*/
const fullSearchTitle = computed(() => {
return `${pageLocale?.searchTitle ?? ""} ${nameFilter.value}`;
});
return {
nameFilter, // Estado reactivo que almacena el texto actual del filtro de búsqueda
searchedItems, // Lista filtrada
filterProvider, // Función para actualizar el filtro de búsqueda.
fullSearchTitle, // Texto que incluye el valor dinamico del input.
};
}

Implementación típica en un componente que necesita funcionalidad de búsqueda:

// Datos de ejemplo
const pageLocale = { searchTitle: "Resultados de productos llamados:" };
const products = ref([
{ id: 1, title: "Laptop Gamer", category: "Tecnología" },
{ id: 2, title: "Smartphone Pro", category: "Moviles" },
]);
const key = "title"; // Clave con la que se hará la búsqueda. En este caso, 'title', por defecto es 'name'
// Inicialización del composable
const { nameFilter, filterProvider, searchedItems, fullSearchTitle } =
useSearchBar(products.value, pageLocale, key);
<template>
<UiSearchBar @filter-title="filterProvider" />
<h1 v-if="nameFilter">{{ fullSearchTitle }}</h1>
<ul class="results-list">
<li v-for="item in searchedItems" :key="item.id" class="result-item">
{{ item.title }} - {{ item.category }}
</li>
</ul>
</template>