Filtro de búsqueda de cuadrícula Blazor
La función Ignite UI for Blazor Search Filter en Blazor Grid permite el proceso de búsqueda de valores en la recopilación de datos. Hacemos que sea más fácil configurar esta funcionalidad y se puede implementar con un cuadro de entrada de búsqueda, botones, navegación con teclado y otras funciones útiles para una experiencia de usuario aún mejor. Si bien los navegadores brindan de forma nativa la funcionalidad de búsqueda de contenido, la mayoría de las veces IgbGrid
virtualiza sus columnas y filas que están fuera de la vista. En estos casos, la búsqueda del navegador nativo no puede buscar datos en las celdas virtualizadas, ya que no forman parte del DOM. Hemos ampliado la cuadrícula basada en tablas Blazor Material con una API de búsqueda que le permite buscar en el contenido virtualizado de IgbGrid
.
Blazor Search Example
El siguiente ejemplo representa IgbGrid
con un cuadro de entrada de búsqueda que permite buscar en todas las columnas y filas, así como opciones de filtrado específicas para cada columna.
Blazor Search Usage
Grid Setup
Comencemos creando nuestra cuadrícula y vinculándola a nuestros datos. ¡También agregaremos algunos estilos personalizados para los componentes que usaremos!
.gridSize {
--ig-size: var(--ig-size-small);
}
<IgbGrid @ref=grid Class="gridSize" Width="100%" Height="480px" AllowFiltering=true AutoGenerate=false Data=marketData>
<IgbColumn Field="IndustrySector" DataType="GridColumnDataType.String" Sortable=true></IgbColumn>
<IgbColumn Field="IndustryGroup" DataType="GridColumnDataType.String" Sortable=true></IgbColumn>
<IgbColumn Field="SectorType" DataType="GridColumnDataType.String" Sortable=true></IgbColumn>
<IgbColumn Field="KRD" DataType="GridColumnDataType.Number" Sortable=true></IgbColumn>
<IgbColumn Field="MarketNotion" DataType="GridColumnDataType.Number" Sortable=true></IgbColumn>
</IgbGrid>
@code {
protected override void OnInitialized()
{
base.OnInitialized();
this.marketData = MarketData.GetData();
}
}
¡Genial, y ahora preparémonos para la API de búsqueda de nuestro IgbGrid
! Podemos crear algunas propiedades, que se pueden usar para almacenar el texto buscado actualmente y si la búsqueda distingue entre mayúsculas y minúsculas y/o por coincidencia exacta.
public string searchText = "";
public bool caseSensitive = false;
public bool exactMatch = false;
Blazor Search Box Input
¡Ahora creemos nuestra entrada de búsqueda! Al vincular nuestro SearchText
a la propiedad Value
de nuestra entrada recién creada y suscribirnos al evento ValueChanging
, podemos detectar cada modificación SearchText
por parte del usuario. Esto nos permitirá usar los métodos FindNext
y FindPrev
de IgbGrid
para resaltar todas las apariciones de SearchText
y desplazarnos al siguiente/anterior (dependiendo del método que hayamos invocado).
Tanto el método FindNext
como el FindPrev
tienen tres argumentos:
Text
: cadena (el texto que estamos buscando)- (opcional)
CaseSensitive
: booleano (si la búsqueda distingue entre mayúsculas y minúsculas o no, el valor predeterminado es falso) - (opcional)
ExactMatch
: booleano (si la búsqueda se realiza por coincidencia exacta o no, el valor predeterminado es falso)
Al buscar por coincidencia exacta, la API de búsqueda resaltará como resultados solo los valores de celda que coincidan completamente con SearchText
teniendo en cuenta también la distinción entre mayúsculas y minúsculas. Por ejemplo, las cadenas 'software' y 'Software' coinciden exactamente sin tener en cuenta la distinción entre mayúsculas y minúsculas.
Los métodos anteriores devuelven un valor numérico (el número de veces que IgbGrid
contiene la cadena dada).
<IgbInput ValueChanging="valueChanging" Value="@searchText" />
Add Search Buttons
Para buscar y navegar libremente entre nuestros resultados de búsqueda, creemos un par de botones invocando los métodos FindNext
y FindPrev
dentro de los respectivos controladores de eventos de clic de los botones.
<IgbIconButton Variant="IconButtonVariant.Flat" @onclick="PrevSearch">
<IgbIcon IconName="prev" Collection="material"/>
</IgbIconButton>
<IgbIconButton Variant="IconButtonVariant.Flat" @onclick="NextSearch">
<IgbIcon IconName="next" Collection="material" />
</IgbIconButton>
@code {
private IgbGrid grid;
public void PrevSearch()
{
this.grid.FindPrevAsync(this.searchText, this.caseSensitive, this.exactMatch);
}
public void NextSearch()
{
this.grid.FindNextAsync(this.searchText, this.caseSensitive, this.exactMatch);
}
}
Add Keyboard Search
También podemos permitir que los usuarios naveguen por los resultados utilizando las teclas de flecha del teclado y la tecla Intro. Para lograr esto, podemos manejar el evento de pulsación de tecla de nuestra entrada de búsqueda evitando el movimiento del cursor predeterminado de la entrada con el método PreventDefault
e invocando los métodos FindNext
/ FindPrev
dependiendo de qué tecla haya presionado el usuario.
También podemos permitir a los usuarios navegar por los resultados utilizando la tecla Intro del teclado. Para lograr esto, podemos manejar el evento keydown de nuestra búsqueda e invocar los métodos FindNext
/ FindPrev
dependiendo de si el usuario también ha presionado Shift o no.
<IgbInput ValueChanging="valueChanging" Value="@searchText" @onkeydown="OnSearchKeyDown"/>
@code {
private void OnSearchKeyDown(KeyboardEventArgs evt)
{
if (evt.Key == "Enter" && !evt.ShiftKey) {
this.grid.FindNextAsync(this.searchText, this.caseSensitive, this.exactMatch);
} else if (evt.Key == "Enter") {
this.grid.FindPrevAsync(this.searchText, this.caseSensitive, this.exactMatch);
}
}
}
Case Sensitive and Exact Match
Ahora permitamos que el usuario elija si la búsqueda debe distinguir entre mayúsculas y minúsculas y/o por una coincidencia exacta. Para este propósito, podemos usar Chips
seleccionables simples y vincularnos al evento SelectedChanged
para determinar cuándo el usuario interactúa con ellos.
<IgbChip Selectable=true SelectedChanged="UpdateCase">
Case Sensitive
</IgbChip>
<IgbChip Selectable=true SelectedChanged="UpdateExactSearch">
Exact Match
</IgbChip>
@code {
public void UpdateCase(bool selected) {
this.caseSensitive = selected;
this.grid.FindNextAsync(this.searchText, this.caseSensitive, this.exactMatch);
}
public void UpdateExactSearch(bool selected) {
this.exactMatch = selected;
this.grid.FindNextAsync(this.searchText, this.caseSensitive, this.exactMatch);
}
}
Persistence
¿Qué pasa si quisiéramos filtrar y ordenar nuestros IgbGrid
¿O incluso para agregar y eliminar registros? Después de tales operaciones, los aspectos más destacados de nuestra búsqueda actual se actualizan automáticamente y persisten sobre cualquier texto que coincida con el SearchText
! Además, la búsqueda funcionará con paginación y persistirá los aspectos más destacados a través de cambios en el IgbGrid
's PerPage
propiedad.
Adding icons
Al utilizar algunos de nuestros otros componentes, podemos crear una interfaz de usuario enriquecida y mejorar el diseño general de toda nuestra barra de búsqueda. Podemos tener un bonito icono de búsqueda o eliminación a la izquierda de la entrada de búsqueda, un par de chips para nuestras opciones de búsqueda y algunos iconos de diseño de materiales combinados con bonitos botones de estilo ondulado para nuestra navegación a la derecha. Podemos envolver estos componentes dentro de un grupo de entrada para un diseño más refinado.
Para hacer esto, tomemos los módulos IgbInput
, IgbIcon
, IgbIconButton
e IgbChip
.
// eg. Program.cs register the following:
builder.Services.AddIgniteUIBlazor(
typeof(IgbGridModule),
typeof(IgbInputModule),
typeof(IgbIconButtonModule),
typeof(IgbIconModule)
);
@code {
private IgbIcon searchIconRef { get; set; }
const string searchIcon = "<svg width='24' height='24' viewBox='0 0 24 24'><path d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z' /></svg>";
const string prevIcon = "<svg width='24' height='24' viewBox='0 0 24 24'><path d='M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z'></path></svg>";
const string nextIcon = "<svg width='24' height='24' viewBox='0 0 24 24'><path d='M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'></path></svg>";
const string clearIcon = "<svg width='24' height='24' viewBox='0 0 24 24' title='Clear'><path d='M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'></path></svg>";
protected override void OnAfterRender(bool firstRender)
{
if (this.searchIconRef != null && firstRender)
{
this.searchIconRef.EnsureReady().ContinueWith(new Action<Task>((e) =>
{
this.searchIconRef.RegisterIconFromTextAsync("search", searchIcon, "material");
this.searchIconRef.RegisterIconFromTextAsync("prev", prevIcon, "material");
this.searchIconRef.RegisterIconFromTextAsync("next", nextIcon, "material");
this.searchIconRef.RegisterIconFromTextAsync("clear", clearIcon, "material");
}));
}
}
}
Finalmente, ¡actualicemos nuestra plantilla con los nuevos componentes!
Envolveremos todos nuestros componentes dentro de un IgbInput
. A la izquierda alternaremos entre una búsqueda y un icono de eliminar/borrar (dependiendo de si la entrada de búsqueda está vacía o no). En el centro posicionaremos la propia entrada. Además, cada vez que se haga clic en el icono de eliminación, actualizaremos nuestro SearchText
e invocaremos el método ClearSearch
de IgbGrid
para borrar los aspectos destacados.
<IgbInput ValueChanging="OnValueChanging" Value="@searchText" @onkeydown="OnSearchKeyDown">
@if (searchText.Length == 0)
{
<IgbIcon @ref="searchIconRef" slot="prefix" IconName="search" Collection="material"/>
}
@if (searchText.Length > 0)
{
<IgbIcon slot="prefix" IconName="clear" Collection="material" @onclick="ClearSearch"/>
}
<div class="chips" slot="suffix">
<IgbChip Selectable=true SelectedChanged="UpdateCase">
Case Sensitive
</IgbChip>
<IgbChip Selectable=true SelectedChanged="UpdateExactSearch">
Exact Match
</IgbChip>
</div>
<div class="searchButtons" slot="suffix">
<IgbIconButton Variant="IconButtonVariant.Flat" @onclick="PrevSearch">
<IgbIcon IconName="prev" Collection="material"/>
</IgbIconButton>
<IgbIconButton Variant="IconButtonVariant.Flat" @onclick="NextSearch">
<IgbIcon IconName="next" Collection="material" />
</IgbIconButton>
</div>
</IgbInput>
@code {
public void clearSearch()
{
this.searchText = "";
this.grid.ClearSearchAsync();
}
}
A la derecha de nuestro grupo de entrada, creemos tres contenedores separados con los siguientes propósitos:
- Para mostrar un par de chips que alternan las propiedades
CaseSensitive
yExactMatch
. Hemos reemplazado las casillas de verificación con dos chips elegantes que cambian de color según estas propiedades. Cada vez que se hace clic en un chip, invocamos su respectivo controlador.
<div class="chips" slot="suffix">
<IgbChip Selectable=true SelectedChanged="UpdateCase">
Case Sensitive
</IgbChip>
<IgbChip Selectable=true SelectedChanged="UpdateExactSearch">
Exact Match
</IgbChip>
</div>
@code {
public void UpdateCase(bool selected) {
this.caseSensitive = selected;
this.grid.FindNextAsync(this.searchText, this.caseSensitive, this.exactMatch);
}
public void UpdateExactSearch(bool selected) {
this.exactMatch = selected;
this.grid.FindNextAsync(this.searchText, this.caseSensitive, this.exactMatch);
}
}
- Para los botones de navegación de búsqueda, hemos transformado nuestras entradas en botones de estilo ondulado con íconos de materiales. Los controladores para los eventos de clic siguen siendo los mismos: invocando los métodos
FindNext
/FindPrev
.
<div class="searchButtons" slot="suffix">
<IgbIconButton Variant="IconButtonVariant.Flat" @onclick="PrevSearch">
<IgbIcon IconName="prev" Collection="material"/>
</IgbIconButton>
<IgbIconButton Variant="IconButtonVariant.Flat" @onclick="NextSearch">
<IgbIcon IconName="next" Collection="material" />
</IgbIconButton>
</div>
@code {
public void PrevSearch()
{
this.grid.FindPrevAsync(this.searchText, this.caseSensitive, this.exactMatch);
}
public void NextSearch()
{
this.grid.FindNextAsync(this.searchText, this.caseSensitive, this.exactMatch);
}
}
Known Limitations
Limitación | Descripción |
---|---|
Buscando en celdas con una plantilla | Las funciones destacadas de búsqueda funcionan solo para las plantillas de celda predeterminadas. Si tiene una columna con una plantilla de celda personalizada, los resaltados no funcionarán, por lo que deberá utilizar enfoques alternativos, como un formateador de columnas, o configurar elSearchable propiedad en la columna a falso. |
Virtualización remota | La búsqueda no funcionará correctamente al utilizar la virtualización remota |
Celdas con texto cortado | Cuando el texto en la celda es demasiado grande para caber y el texto que estamos buscando está cortado por los puntos suspensivos, aún nos desplazaremos hasta la celda y la incluiremos en el recuento de coincidencias, pero no se resaltará nada. |
API References
En este artículo implementamos nuestra propia barra de búsqueda para IgbGrid
con algunas funciones adicionales cuando se trata de navegar entre los resultados de búsqueda. También utilizamos algunas Ignite UI for Blazor como íconos, chips y entradas. La API de búsqueda se enumera a continuación.
IgbGrid
methods:
IgbColumn
properties:
Componentes adicionales con API relativas que se utilizaron:
Additional Resources
- Virtualización y rendimiento
- Filtración
- Paginación
- Clasificación
- resúmenes
- Columna en movimiento
- Fijación de columnas
- Cambio de tamaño de columna
- Selección
Nuestra comunidad es activa y siempre da la bienvenida a nuevas ideas.