Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply highlight for material datatable filter

I want to highlight the text that is searched in the datatable filter field, I am using material data table with angular. I create a pipe for highlight, and send the text search as an arg

export class HighlightSearchPipe implements PipeTransform {
 private destroyed$: Subject<void> = new ReplaySubject(1);

 constructor( private sanitizer: DomSanitizer) {}

transform(value: any, args?: any): any {
   if (!value) {
   return observableOf(value);
  }

/** Data table filtering */
if (args) {
  const searchText = args[0];
  const re = new RegExp(searchText, 'gi');
  const match = value.match(re);
  // If there's no match, just return the original value.
  if (!match) {
    return value;
  }
  value = value.replace(re, '<mark class="saqr-first-mark">' + match[0] + '</mark>');
  return observableOf(value);
}

and in the material datatable typescript file I add the highlight into the constructor

constructor(
private highlight: HighlightSearchPipe,
 ) {}

applyFilter() {
 this.dataSource.filter = this.searchKeyword.trim().toLowerCase();
 this.highlight.transform(this.dataSource.filter, this.searchKeyword);  
// here cannot detect that 
}

What do you suggest to do for data table highlighting the searched text?

like image 865
palAlaa Avatar asked Feb 26 '19 05:02

palAlaa


1 Answers

I've managed to produce a working demo of this. My HighlightSearchPipe class is as follows:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'highlightSearch'
})
export class HighlightSearchPipe implements PipeTransform {

  transform(value: string, search: string): string {
    const valueStr = value + ''; // Ensure numeric values are converted to strings
    return valueStr.replace(new RegExp('(?![^&;]+;)(?!<[^<>]*)(' + search + ')(?![^<>]*>)(?![^&;]+;)', 'gi'), '<strong class="your-class">$1</strong>');
  }
}

I've modified Typescript class that contains the applyFilter() function as follows:

i. Added the filterText class variable so the filter text typed by the user can be accessed in the HTML. This variable is updated in the applyFilter() function

ii. Removed the call to this.highlight.transform(this.dataSource.filter, this.searchKeyword); in applyFilter()

@Component({
  ...
})
export class TableFilteringExample {
  ...
  filterText = '';

  applyFilter(filterValue: string) {
    this.filterText = filterValue.trim();
    this.dataSource.filter = this.filterText.toLowerCase();
  }
}

In the component HTML I've changed the way the cells are rendered from:

<ng-container matColumnDef="name">
  <th mat-header-cell *matHeaderCellDef> Name </th>
  <td mat-cell *matCellDef="let element">{{element.name}}</td>
</ng-container>

to:

<ng-container matColumnDef="name">
  <th mat-header-cell *matHeaderCellDef> Name </th>
  <td mat-cell *matCellDef="let element" [innerHTML]="element.name | highlightSearch: filterText"></td>
</ng-container>

This way the cell value (in this case element.name) is capable of rendering HTML. It uses the highlightSearch pipe in order to transform the value and highlight the portion of it that matches the filter.

like image 107
Ian A Avatar answered Sep 20 '22 00:09

Ian A