Descripción general de la directiva de resaltado de texto Angular

    Los IgxTextHighlightDirective y IgxTextHighlightService en Ignite UI for Angular se utilizan para resaltar partes de un texto, proporcionando opciones para búsquedas que distinguen entre mayúsculas y minúsculas y para resaltar solo coincidencias exactas. Permiten al desarrollador mantener un resaltado activo, que puede ser cualquiera de las partes ya resaltadas.

    Angular Text Highlight Directive Example

    Getting Started with Ignite UI for Angular Text Highlight Directive

    Para comenzar con la directiva Ignite UI for Angular Text Highlight, primero debe instalar Ignite UI for Angular. En una aplicación Angular existente, escriba el siguiente comando:

    ng add igniteui-angular
    

    Para obtener una introducción completa a la Ignite UI for Angular, lea el tema de introducción.

    El siguiente paso es importar IgxTextHighlightModule en su archivo app.module.ts.

    // app.module.ts
    ...
    import { IgxTextHighlightModule } from 'igniteui-angular';
    // import { IgxTextHighlightModule } from '@infragistics/igniteui-angular'; for licensed package
    
    @NgModule({
        ...
        imports: [IgxTextHighlightModule],
        ...
    })
    export class AppModule {}
    

    Alternativamente, a partir de 16.0.0 puede importar IgxTextHighlightDirective como una dependencia independiente.

    // home.component.ts
    
    import { IgxTextHighlightDirective, IgxTextHighlightService } from 'igniteui-angular';
    // import { IgxTextHighlightDirective, IgxTextHighlightService } from '@infragistics/igniteui-angular'; for licensed package
    
    @Component({
        selector: 'app-home',
        template: `
        <div igxTextHighlight
            [value]="html"
            [groupName]="'group1'"
            [containerClass]="'search-text'"
            class="search-text">
            {{html}}
        </div>
        `,
        styleUrls: ['home.component.scss'],
        standalone: true,
        imports: [IgxTextHighlightDirective]
    })
    export class HomeComponent {
        constructor(public textHighlightService: IgxTextHighlightService) {}
    }
    

    Ahora que tiene importado el módulo o la directiva Ignite UI for Angular Text Salt, puede comenzar a usar el igxTextHighlight.

    Using the Angular Text Highlight Directive

    Creemos un cuadro de búsqueda que podamos usar para resaltar diferentes partes del texto. Usaremos Ignite UI for Angular Grupo de entrada componente en el que agregaremos una entrada de texto con botones para borrar coincidencias, buscar siguiente, buscar anterior y un botón para especificar si la búsqueda distinguirá entre mayúsculas y minúsculas o no. También tiene una etiqueta que indica cuántas coincidencias hemos encontrado.

    <div class="search-container">
        <igx-input-group type="search" class="input-group">
            <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" autocomplete="off" [(ngModel)]="searchText" (ngModelChange)="onTextboxChange()"
                    (keydown)="searchKeyDown($event)" />
            <igx-suffix>
                <div class="caseSensitiveButton">
                    <button igxIconButton="flat" igxRipple igxRippleCentered="true" (click)="updateSearch()"
                            [style.background]="caseSensitive ? 'rgb(73, 180, 254)' : 'transparent'">
                        <igx-icon class="caseSensitiveIcon" fontSet="material">text_fields</igx-icon>
                    </button>
                </div>
                <ng-container *ngIf="searchText.length > 0">
                    <span>
                        <ng-container *ngIf="matchCount > 0">
                            {{ index + 1 }} of {{ matchCount }} results
                        </ng-container>
                        <ng-container *ngIf="matchCount == 0">
                            No results
                        </ng-container>
                    </span>
                </ng-container>
               
                <div class="searchButtons">
                    <button igxIconButton="flat" igxRipple igxRippleCentered="true" (click)="findPrev()" [disabled]="!canMoveHighlight">
                        <igx-icon fontSet="material">navigate_before</igx-icon>
                    </button>
                    <button igIconButton="flat" igxRipple igxRippleCentered="true" (click)="findNext()" [disabled]="!canMoveHighlight">
                        <igx-icon fontSet="material">navigate_next</igx-icon>
                    </button>
                </div>
            </igx-suffix>
        </igx-input-group>
    </div>
    

    Luego, agregaremos un div con texto y la directiva IgxTextHighlight. Tenga en cuenta que, dado que necesitamos vincular la entrada del valor al texto en el div, también usaremos la interpolación para el texto del div.

    <div igxTextHighlight
         [value]="html"
         [groupName]="'group1'"
         [containerClass]="'search-text'"
         class="search-text">
        {{html}}
    </div>
    

    En el archivo .ts de nuestro componente, primero debemos agregar los siguientes campos, que se utilizan para los enlaces en la plantilla de nuestro componente:

    @Component({
        ...
    })
    export class HomeComponent {
        public html = '...';
    
        @ViewChild(IgxTextHighlightDirective, {read: IgxTextHighlightDirective})
        public highlight: IgxTextHighlightDirective;
    
        public searchText: string = '';
        public matchCount: number = 0;
        public caseSensitive: boolean = false;
        public index: number = 0;
    
        public get canMoveHighlight() {
            return this.matchCount > 1;
        }
    }
    

    Luego, debemos agregar los siguientes métodos que permitirán al usuario aplicar resaltados al texto que ha escrito en el cuadro de búsqueda y mover el resaltado activo.

    @Component({
        ...
    })
    export class HomeComponent {
        constructor(public textHighlightService: IgxTextHighlightService) {}
    
        public searchKeyDown(ev) {
            if (this.searchText) {
                if (ev.key === 'Enter' || ev.key === 'ArrowDown' || ev.key === 'ArrowRight') {
                    ev.preventDefault();
                    this.findNext();
                } else if (ev.key === 'ArrowUp' || ev.key === 'ArrowLeft') {
                    ev.preventDefault();
                    this.findPrev();
                }
            }
        }
    
        public onTextboxChange() {
            this.index = 0;
            this.find(0);
        }
    
        public updateSearch() {
            this.caseSensitive = !this.caseSensitive;
            this.find(0);
        }
    
        public clearSearch() {
            this.searchText = '';
            this.find(0);
        }
    
        private findNext() {
            this.find(1);
        }
    
        private findPrev() {
            this.find(-1);
        }
    
        private find(increment: number) {
            if (this.searchText) {
                this.matchCount = this.highlight.highlight(this.searchText, this.caseSensitive);
                this.index += increment;
    
                this.index = this.index < 0 ? this.matchCount - 1 : this.index;
                this.index = this.index > this.matchCount - 1 ? 0 : this.index;
    
                if (this.matchCount) {
                    this.textHighlightService.setActiveHighlight('group1', {
                        columnIndex: 0,
                        index: this.index,
                        page: 0,
                        rowIndex: 0
                    });
                }
            } else {
                this.highlight.clearHighlight();
            }
        }
    }
    

    Si la muestra está configurada correctamente, el resultado final debería verse así:

    Search across multiple elements

    igxTextHighlight le permite buscar en múltiples elementos que comparten un resaltado activo. Esto se hace teniendo el mismo valor groupName en varias directivas TextHighlight. Para configurar el ejemplo reutilizaremos el cuadro de búsqueda del ejemplo anterior, pero esta vez agregaremos dos elementos div. Las entradas column y row son útiles cuando tienes varios elementos y, en nuestro caso, el segundo div tiene un valor de fila diferente.

    <div igxTextHighlight
         [groupName]="'group1'"
         [row]="0"
         [containerClass]="'search-text'"
         [value]="firstParagraph"
         class="search-text">
        {{firstParagraph}}
    </div>
    <div igxTextHighlight
         [groupName]="'group1'"
         [row]="1"
         [containerClass]="'search-text'"
         [value]="secondParagraph"
         class="search-text">
        {{secondParagraph}}
    </div>
    

    En el archivo .ts tenemos los campos firstParagraph y secondParagraph, que están vinculados a las respectivas entradas de valor de las directivas de resaltado de texto. Además, ahora usaremos ViewChildren en lugar de ViewChild para obtener todos los aspectos destacados de nuestra plantilla.

    public firstParagraph = "...";
    
    public secondParagraph = "...";
    
    @ViewChildren(IgxTextHighlightDirective)
    public highlights;
    

    Todo el resto del código en el archivo .ts es idéntico al ejemplo de elemento único con la excepción del método de búsqueda. Los cambios en este método son necesarios ya que ahora tenemos varios elementos, pero el código allí se puede usar independientemente de la cantidad de directivas TextHighlight que tenga en su página.

    @Component({
        ...
    })
    export class HomeComponent {
        constructor(public textHighlightService: IgxTextHighlightService) {}
    
        private find(increment: number) {
            if (this.searchText) {
                let count = 0;
                const matchesArray = [];
    
                this.highlights.forEach((h) => {
                    count += h.highlight(this.searchText, this.caseSensitive);
                    matchesArray.push(count);
                });
    
                this.matchCount = count;
    
                this.index += increment;
                this.index = this.index < 0 ? this.matchCount - 1 : this.index;
                this.index = this.index > this.matchCount - 1 ? 0 : this.index;
    
                if (this.matchCount) {
                    let row;
    
                    for (let i = 0; i < matchesArray.length; i++) {
                        if (this.index < matchesArray[i]) {
                            row = i;
                            break;
                        }
                    }
    
                    const actualIndex = row === 0 ? this.index : this.index - matchesArray[row - 1];
    
                    this.textHighlightService.setActiveHighlight('group1', {
                        index: actualIndex,
                        rowIndex: row
                    });
                }
            } else {
                this.highlights.forEach((h) => {
                    h.clearHighlight();
                });
                this.matchCount = 0;
            }
        }
    }
    

    Styles

    A la directiva IgxTextHighlight se le puede aplicar estilo en términos de cambiar el color y el fondo de todas las apariciones de la cadena dada. Para comenzar, necesitamos importar el archivo index, donde se encuentran todas las funciones del tema y los mixins de componentes:

    @use "igniteui-angular/theming" as *;
    
    // IMPORTANT: Prior to Ignite UI for Angular version 13 use:
    // @import '~igniteui-angular/lib/core/styles/themes/index';
    

    Siguiendo el enfoque más simple, creamos un nuevo tema que extiende el highlight-theme y acepta los parámetros $resting-background, $resting-color, $active-background y $active-color.

    $dark-highlight: highlight-theme(
        $resting-background: #FFCD0F,
        $resting-color: #292826,
        $active-background: #292826,
        $active-color: #FFCD0F
    );
    

    Los parámetros $resting-background y $resting-color se aplicarán a todas las ocurrencias resaltadas, excepto a la cadena resaltada activa, cuyo estilo se diseñará según los parámetros $active-background y $active-color.

    El último paso es incluir el tema recién creado.

    Si $legacy-support está configurado en true, incluya el tema del componente así:

    @include highlight($dark-highlight);
    
    Note

    Si el componente utiliza una ViewEncapsulation Emulated, es necesario penetrar esta encapsulación usando::ng-deep:

    :host {
        ::ng-deep {
            @include highlight($dark-highlight);
        }
    }
    

    Si $legacy-support está configurado en false (predeterminado), incluya las variables CSS del componente así:

    @include css-vars($dark-highlight);
    
    Note

    Tenga en cuenta que, de forma predeterminada, $legacy-support está configurado en false

    Custom styles

    Digamos que queremos proporcionar un estilo aún más rico a nuestras partes de texto resaltadas. Para hacer esto, podemos aprovechar las entradas cssClass y activeCssClass de la directiva IgxTextHighlight. ¡Podemos combinar estas clases con los estilos del highlight-theme y brindar una experiencia increíble a nuestros usuarios!

    Todo lo que tenemos que hacer es crear un par de clases CSS con algunas propiedades y adjuntarlas usando las entradas anteriores:

    <div igxTextHighlight
         [cssClass]="'custom-highlight'"
         [activeCssClass]="'custom-active-highlight'">
        {{html}}
    </div>
    
    // cssClass
    .custom-highlight {
        border: 1px solid #FFCD0F;
    }
    // activeCssClass
    .custom-active-highlight {
        box-shadow: 0 0 3px 0 rgba(0,0,0,0.75);
    }
    

    Como mencionamos anteriormente, incluso podemos combinarlos con un tema:

    :host {
        ::ng-deep {
           @include highlight($dark-highlight);
            
           // cssClass
           .custom-highlight {
                border: 1px solid #FFCD0F;
           }
            
            // activeCssClass
           .custom-active-highlight {
                box-shadow: 0 0 3px 0 rgba(0,0,0,0.75);
            }
       }
    }
    

    Demo

    API References

    Para obtener información más detallada sobre la API de la directiva TextHighlight, consulte el siguiente enlace:

    Componentes adicionales que se utilizaron:

    Additional Resources

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