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

    ¡Ahora vamos a crear nuestra entrada de búsqueda! Al vincular nuestro searchText como ngModel a nuestra entrada recién creada y suscribirnos al evento ngModelChange, podemos detectar cada modificación de searchText realizada por el usuario. Esto nos permitirá usar las CuadrículasfindNext de Árbol yfindPrev los métodos para resaltar todas las apariencias del searchText y desplazarnos al siguiente/anterior (dependiendo del método que hayamos invocado).

    Tanto los métodos comofindNext losfindPrev tienen tres argumentos:

    • text: string (el texto que buscamos)
    • (opcional)caseSensitive: booleano (si la búsqueda es sensible a mayúsculas y minúsculas o no, el valor por defecto es falso)
    • (opcional)exactMatch: booleano (si la búsqueda es exactamente coincidente o no, el valor por defecto es falso)

    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

    ¡Vamos también a mostrar la posición del suceso actual junto con el recuento total de resultados! Podemos hacerlo usando la propiedad delastSearchInfo la cuadrícula. Esta propiedad se actualiza automáticamente al usar los métodos de búsqueda.

    • EltreeGrid.lastSearchInfo.matchInfoCache.length valor nos dará el recuento total de resultados.
    • EltreeGrid.lastSearchInfo.activeMatchIndex valor nos dará la posición índice de la ocurrencia actual (coincidencia).
    <!--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

    Para buscar y navegar libremente entre nuestros resultados, creemos un par de botones invocando losfindNext métodos yfindPrev dentro de los respectivos manejadores de eventos de clic.

    <!--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>
    

    También podemos permitir que los usuarios naveguen por los resultados usando las flechas del teclado y la tecla Enter. Para lograr esto, podemos manejar el evento keydown de nuestra entrada de búsqueda impidiendo el movimiento predeterminado del caret de la entrada con el método preventDefault() e invocar elfindNext /findPrev métodos dependiendo de la tecla que el usuario haya pulsado.

    <!--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

    Ahora permitamos al usuario elegir si la búsqueda debe ser sensible a mayúsculas y minúsculas y/o con una coincidencia exacta. Para este propósito podemos usar entradas simples de casillas de verificación vinculando nuestras propiedades caseSensitive y exactMatch a las propiedades comprobadas de las entradas respectivamente y gestionar sus eventos de cambio alternando nuestras propiedades e invocando elfindNext método.

    <!--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

    ¿Y si quisiéramos filtrar y ordenar nuestra Tree Grid o incluso añadir y eliminar registros? Tras estas operaciones, los aspectos destacados de nuestra búsqueda actual se actualizan y persisten automáticamente sobre cualquier texto que coincida con el Texto de búsqueda. Además, la búsqueda funcionará con paginación y mantendrá los resaltados mediante cambios en la propiedad de laperPage Cuadrícula de Árbol.

    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!

    Envolveremos todos nuestros componentes dentro de un IgxInputGroup. A la izquierda alternaremos entre un icono de búsqueda y un icono de borrar/borrar (dependiendo de si la entrada de búsqueda está vacía o no). En el centro, posicionaremos la entrada en sí. Además, cada vez que se haga clic en el icono de eliminar, actualizaremos nuestro searchText e invocaremos el método declearSearch la Cuadrícula de Árbol para eliminar los resaltados.

    <!--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>
        ...
    
    • Para los botones de navegación de búsqueda, hemos transformado nuestras entradas en botones de estilo ondulado con iconos de material. Los manejadores para los eventos de clic siguen siendo los mismos: invocar losfindNext métodosfindPrev (o/métodos).
    <!--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:

    IBuscarInfo

    Componentes adicionales y/o directivas con API relativas que se utilizaron:

    Styles:

    Additional Resources

    Nuestra comunidad es activa y siempre da la bienvenida a nuevas ideas.