highlight.directive.ts
import {
Directive,
HostBinding,
Input,
OnChanges,
SecurityContext,
SimpleChanges
} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { escapeRegExpSpecialChars } from '../../functions/escape-regular-expression-special-chars.function';
@Directive({
selector: '[highlight]'
})
export class HighlightDirective implements OnChanges {
/**
* Text to search with
*/
@Input('highlight') searchTerm: string | null = null;
/**
* The full text from which the search will apply
*/
@Input() fullText: string | null = null;
/**
* Is case sensitive or not. Pass __true__ for case sensitive search.
*
* Default is false
*/
@Input() caseSensitive: boolean = false;
/**
* Any additional custom class for the highlited text.
*
* Default is '';
*/
@Input() customClasses: string = '';
/**
* The property that is going to binded after the search
*/
@HostBinding('innerHTML')
private content: string | null = null;
constructor(
// private readonly _element: ElementRef,
private readonly _sanitizer: DomSanitizer
) { }
ngOnChanges(changes: SimpleChanges): void {
this.content = this.fullText;
if (!this.fullText) {
// console.log(
// "%cPlease give full text to highlight text",
// "color: red; font-size: 16px",
// "\nExample: <span [highlight]='he' [fullText]='text'>{{ text }}</span>\nIt will highlight he from {{text}}"
// );
return;
}
// To convert any type of data to string
// User may pass number, date or any other type of data
this.fullText = this.fullText + '';
const searchTerm = changes["searchTerm"];
if (!searchTerm) {
return;
}
// get current value of the search term
const currentSearchTerm = searchTerm["currentValue"];
if (!currentSearchTerm) {
return;
}
// g: case sensitive
// gi: case insensitive
const regex = new RegExp(escapeRegExpSpecialChars(currentSearchTerm), this.caseSensitive ? 'g' : 'gi');
const highlitedText = this.fullText.replace(regex, (match: string) => {
return `<mark class="${this.customClasses}">${match}</mark>`;
});
// Sanitize the text to avoid xss attack
const sanitizedText = this._sanitizer.sanitize(
SecurityContext.HTML,
highlitedText
);
// insert the text to the innerhtml
this.content = sanitizedText ?? this.content;
}
}Usage in html file
<input matInput (keyup)="applySearchFilter($event)" type="text" #searchInLogConsole>
<table class="table" mat-table [dataSource]="dataSource" matSort>
........
........
<!-- SYSNO Column -->
<ng-container matColumnDef="SYSNO" *ngIf="displayedColumns.includes('SYSNO')">
<th mat-header-cell *matHeaderCellDef mat-sort-header> SYSNO </th>
<td mat-cell *matCellDef="let pc" [highlight]="searchInLogConsole.value" [fullText]="pc.SYSNO">
{{ pc.SYSNO }}
</td>
</ng-container>
........
........
</table>