Filtro de búsqueda de cuadrícula de árbol Angular
Angular búsqueda de cuadrícula de árbol permite el proceso de búsqueda de valores en la recopilación de datos. Facilitamos la configuración de esta funcionalidad y se puede implementar con un cuadro de entrada de búsqueda, botones, navegación por teclado y otras características útiles para una experiencia de usuario aún mejor. Si bien los navegadores proporcionan de forma nativa la funcionalidad de búsqueda de contenido, la mayoría de las veces la cuadrícula de árbol virtualiza sus columnas y filas que están fuera de la vista. En estos casos, la búsqueda de cuadrícula nativa no puede buscar datos en las celdas virtualizadas, ya que no forman parte del DOM. Hemos ampliado la cuadrícula basada en tablas Ignite UI for Angular con una API de búsqueda que le permite buscar a través del contenido virtualizado de la cuadrícula de árbol.
Angular Search Example
El siguiente ejemplo representa una cuadrícula de árbol 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.
Angular 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!
<!--searchgrid.component.html-->
<igx-tree-grid #treeGrid1 [data]="data" [autoGenerate]="false" primaryKey="ID" foreignKey="ParentID" [allowFiltering]="true">
<igx-column [field]="'Name'" dataType="string" [sortable]="true"></igx-column>
<igx-column [field]="'ID'" dataType="number" [sortable]="true"></igx-column>
<igx-column [field]="'Title'" dataType="string" [sortable]="true"></igx-column>
<igx-column [field]="'Age'" dataType="number" [sortable]="true"></igx-column>
<igx-column [field]="'HireDate'" dataType="date" [sortable]="true"></igx-column>
</igx-tree-grid>
/* searchgrid.component.css */
.grid__wrapper {
margin: 15px;
}
.offset {
margin-bottom: 15px;
}
.resultsText {
font-size: 0.875rem;
}
.chips {
margin-left: 5px;
}
.searchButtons {
margin-left: 5px;
}
¡Genial, y ahora preparémonos para la API de búsqueda de nuestro Tree Grid! 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.
// searchgrid.component.ts
public searchText: string = '';
public caseSensitive: boolean = false;
public exactMatch: boolean = false;
Angular search box input
Now let's create our search input! By binding our searchText as ngModel to our newly created input and subscribe to the ngModelChange event, we can detect every single searchText modification by the user. This will allow us to use the Tree Grid's findNext and findPrev methods to highlight all the occurrences of the searchText and scroll to the next/previous one (depending on which method we have invoked).
Both the findNext and the findPrev methods have three arguments:
text: string (the text we are searching for)- (optional)
caseSensitive: boolean (should the search be case sensitive or not, default value is false) - (optional)
exactMatch: boolean (should the search be by an exact match or not, default value is false)
Al buscar por coincidencia exacta, la API de búsqueda resaltará como resultados solo los valores de celda que coincidan completamente con el texto de búsqueda 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 la cuadrícula de árbol contiene la cadena dada).
<!--searchgrid.component.html-->
<input #search1 id="search1" placeholder="Search" [(ngModel)]="searchText" (ngModelChange)="treeGrid.findNext(searchText, caseSensitive, exactMatch)" />
Display results count
Let's also display the position of the current occurrence, along with the total results count! We can do this by using the grid's lastSearchInfo property. This property is automatically updated when using the find methods.
- The
treeGrid.lastSearchInfo.matchInfoCache.lengthvalue will give us the total results count. - The
treeGrid.lastSearchInfo.activeMatchIndexvalue will give us the index position of the current occurrence (match).
<!--searchgrid.component.html-->
<div class="resultsText" *ngIf="treeGrid.lastSearchInfo">
<span *ngIf="treeGrid.lastSearchInfo.matchInfoCache.length > 0">
{{ treeGrid.lastSearchInfo.activeMatchIndex + 1 }} of {{ treeGrid.lastSearchInfo.matchInfoCache.length }} results
</span>
<span *ngIf="treeGrid.lastSearchInfo.matchInfoCache.length == 0">
No results
</span>
</div>
Add search buttons
In order to freely search and navigate among our search results, let's create a couple of buttons by invoking the findNext and the findPrev methods inside the buttons' respective click event handlers.
<!--searchgrid.component.html-->
<div class="searchButtons">
<input type="button" value="Previous" (click)="treeGrid.findPrev(searchText, caseSensitive, exactMatch)" />
<input type="button" value="Next" (click)="treeGrid.findNext(searchText, caseSensitive, exactMatch)" />
</div>
Add keyboard search
We can also allow the users to navigate the results by using the keyboard's arrow keys and the Enter key. In order to achieve this, we can handle the keydown event of our search input by preventing the default caret movement of the input with the preventDefault() method and invoke the findNext/findPrev methods depending on which key the user has pressed.
<!--searchgrid.component.html-->
<input #search1 id="search1" placeholder="Search" [(ngModel)]="searchText" (ngModelChange)="treeGrid.findNext(searchText, caseSensitive, exactMatch)"
(keydown)="searchKeyDown($event)" />
// searchgrid.component.ts
public searchKeyDown(ev) {
if (ev.key === 'Enter' || ev.key === 'ArrowDown' || ev.key === 'ArrowRight') {
ev.preventDefault();
this.treeGrid.findNext(this.searchText, this.caseSensitive, this.exactMatch);
} else if (ev.key === 'ArrowUp' || ev.key === 'ArrowLeft') {
ev.preventDefault();
this.treeGrid.findPrev(this.searchText, this.caseSensitive, this.exactMatch);
}
}
Case sensitive and Exact match
Now let's allow the user to choose whether the search should be case sensitive and/or by an exact match. For this purpose we can use simple checkbox inputs by binding our caseSensitive and exactMatch properties to the inputs' checked properties respectively and handle their change events by toggling our properties and invoking the findNext method.
<!--searchgrid.component.html-->
<span>Case sensitive</span>
<input type="checkbox" [checked]="caseSensitive" (change)="updateSearch()">
<span>Exact match</span>
<input type="checkbox" [checked]="exactMatch" (change)="updateExactSearch()">
// searchgrid.component.ts
public updateSearch() {
this.caseSensitive = !this.caseSensitive;
this.treeGrid.findNext(this.searchText, this.caseSensitive, this.exactMatch);
}
public updateExactSearch() {
this.exactMatch = !this.exactMatch;
this.treeGrid.findNext(this.searchText, this.caseSensitive, this.exactMatch);
}
Persistence
What if we would like to filter and sort our Tree Grid or even to add and remove records? After such operations, the highlights of our current search automatically update and persist over any text that matches the searchText! Furthermore, the search will work with paging and will persist the highlights through changes of the Tree Grid's perPage property.
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 IgxInputGroup, IgxIcon, IgxRipple, IgxButton e IgxChip.
// app.module.ts
...
import {
IgxTreeGridModule,
IgxInputGroupModule,
IgxIconModule,
IgxRippleModule,
IgxButtonModule,
IgxChipsModule
} from 'igniteui-angular';
// import {
// IgxInputGroupModule,
// IgxIconModule,
// IgxRippleModule,
// IgxButtonModule,
// IgxChipsModule
// } from '@infragistics/igniteui-angular'; for licensed package
@NgModule({
...
imports: [..., IgxInputGroupModule, IgxIconModule, IgxRippleModule, IgxButtonModule, IgxChipsModule],
})
export class AppModule {}
Finalmente, ¡actualicemos nuestra plantilla con los nuevos componentes!
We will wrap all of our components inside an IgxInputGroup. On the left we will toggle between a search and a delete/clear icon (depending on whether the search input is empty or not). In the center, we will position the input itself. In addition, whenever the delete icon is clicked, we will update our searchText and invoke the Tree Grid's clearSearch method to clear the highlights.
<!--searchgrid.component.html-->
<igx-input-group type="search" class="offset">
<igx-prefix>
<igx-icon *ngIf="searchText.length == 0">search</igx-icon>
<igx-icon *ngIf="searchText.length > 0" (click)="clearSearch()">clear</igx-icon>
</igx-prefix>
<input #search1 id="search1" igxInput placeholder="Search" [(ngModel)]="searchText" (ngModelChange)="treeGrid.findNext(searchText, caseSensitive, exactMatch)"
(keydown)="searchKeyDown($event)" />
<igx-suffix *ngIf="searchText.length > 0">
...
</igx-suffix>
</igx-input-group>
// searchgrid.component.ts
public clearSearch() {
this.searchText = '';
this.treeGrid.clearSearch();
}
A la derecha de nuestro grupo de entrada, creemos tres contenedores separados con los siguientes propósitos:
- Para mostrar los resultados de la búsqueda.
<!--searchgrid.component.html-->
<igx-suffix *ngIf="searchText.length > 0">
<div class="resultsText" *ngIf="treeGrid.lastSearchInfo">
<span *ngIf="treeGrid.lastSearchInfo.matchInfoCache.length > 0">
{{ treeGrid.lastSearchInfo.activeMatchIndex + 1 }} of {{ treeGrid.lastSearchInfo.matchInfoCache.length }} results
</span>
<span *ngIf="treeGrid.lastSearchInfo.matchInfoCache.length == 0">
No results
</span>
</div>
</igx-suffix>
- Para mostrar un par de chips que alternan las propiedades caseSensitive y exactitudMatch. 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 controlador respectivo: updateSearch o updateExactSearch dependiendo del chip en el que se haya hecho clic.
<!--searchgrid.component.html-->
...
<div class="chips">
<igx-chips-area>
<igx-chip (click)="updateSearch()" [color]="caseSensitive? 'lightgrey' : 'rgba(0, 0, 0, .04)'">
<span>Case Sensitive</span>
</igx-chip>
<igx-chip (click)="updateExactSearch()" [color]="exactMatch? 'lightgrey' : 'rgba(0, 0, 0, .04)'">
<span>Exact Match</span>
</igx-chip>
</igx-chips-area>
</div>
...
- For the search navigation buttons, we have transformed our inputs into ripple styled buttons with material icons. The handlers for the click events remain the same - invoking the
findNext/findPrevmethods.
<!--searchgrid.component.html-->
<igx-suffix>
<div class="searchButtons">
<button igxIconButton="flat" igxRipple igxRippleCentered="true" (click)="treeGrid.findPrev(searchText, caseSensitive, exactMatch)">
<igx-icon fontSet="material">navigate_before</igx-icon>
</button>
<button igxIconButton="flat" igxRipple igxRippleCentered="true" (click)="treeGrid.findNext(searchText, caseSensitive, exactMatch)">
<igx-icon fontSet="material">navigate_next</igx-icon>
</button>
</div>
</igx-suffix>
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 la cuadrícula de árboles con algunas funciones adicionales a la hora de navegar entre los resultados de búsqueda. También utilizamos algunos componentes Ignite UI for Angular adicionales como iconos, chips y entradas. La API de búsqueda se enumera a continuación.
IgxTreeGridComponent methods:
IgxGridCell methods:
IgxColumnComponent properties:
Componentes adicionales y/o directivas con API relativas que se utilizaron:
- Componente IgxInputGroup
- Componente IgxIcon
- Directiva IgxRipple
- DirectivaBotónIgx
- Componente IgxChip
Styles:
- IgxTreeGridComponent Styles
- Estilos de componentes IgxInputGroup
- Estilos de componentes IgxIcon
- IgxRippleEstilos Directivos
- Estilos de directiva IgxButton
- Estilos de componentes IgxChip
Additional Resources
- Descripción general de la cuadrícula de árbol
- 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