Building a Search and Highlight Feature in Angular

Cover Photo by Aaron Burden on Unsplash

This post walks through implementing a search and highlight capability in an Angular application. The use case is straightforward: you have a lengthy body of text, and users should be able to type a query into an input field, with matching substrings in the paragraph being visually highlighted below.

The setup is minimal — a search input and a target text area (sample dummy text is used for demonstration):
Start screen

The input is bound via ngModel, serving as the search term, while a div holds the sample text rendered with innerHtml.

<div class="search-input">
 <label for="">Search here: </label> <input [(ngModel)]="searchText" type="search">
</div>

<div class="text-contaniner" [innerHtml]="text"  >
 </div>
Enter fullscreen mode Exit fullscreen mode
export class AppComponent {
  searchText='';
  text=`somedummy text here`
}
Enter fullscreen mode Exit fullscreen mode

To enable the highlighting logic, an Angular pipe — named highlighter — is required. Generate it with the Angular CLI command:

ng g pipe highlighter
Enter fullscreen mode Exit fullscreen mode

Enforce a word-boundary constraint in the pipe by using the following code:

 transform(value: any, args: any): unknown {
    if(!args) return value;
      const re = new RegExp("\\b("+args+"\\b)", 'igm');
      value= value.replace(re, '<span class="highlighted-text">$1</span>');
      return value;
  }
Enter fullscreen mode Exit fullscreen mode

For matches that ignore word boundaries — finding the search term anywhere in the text — use this alternative:

 transform(value: any, args: any): unknown {
    if(!args) return value;
      const re = new RegExp("\\b("+args+"\\b)", 'igm');
      value= value.replace(re, '<span class="highlighted-text">$&</span>');
      return value;
  }
Enter fullscreen mode Exit fullscreen mode

To support both behaviors, incorporate a boolean input into the pipe that toggles between partial and full-word matching, merging the two approaches into a single, purpose-driven pipe:

 transform(value: any, args: any,type:string): unknown {
    if(!args) return value;
    if(type==='full'){
      const re = new RegExp("\\b("+args+"\\b)", 'igm');
      value= value.replace(re, '<span class="highlighted-text">$1</span>');
    }
    else{
      const re = new RegExp(args, 'igm');
      value= value.replace(re, '<span class="highlighted-text">$&</span>');
    }

      return value;
  }
Enter fullscreen mode Exit fullscreen mode

Once the two inputs are added, the interface appears as follows:
2inputs screen

Integrate the pipe into the HTML template by applying it to the sample text, passing the user’s input as the search term and the search criteria:

<div class="text-contaniner" [innerHtml]="text | highlighter:searchText:'full'"  >
Enter fullscreen mode Exit fullscreen mode

The complete source is available on GitHub.
Testing the implementation confirms that text is highlighted correctly in both modes. You can try the live demo at https://nikhild64.github.io/highlight-text/:
working example
If you found this useful, feel free to share it with colleagues. For any questions or alternative approaches, leave a comment below or reach out on Twitter. Happy coding!