Highlight Search Results with an Angular Pipe
Tags: angular, javascript
Published: 2020-08-28 00:27:42

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/jwnwcuyz47ih6xrkn1aj.gif)

I remember a few months back (at my previous job) I needed to implement a feature that would highlight text that I searched for in an input. I cannot remember my exact implementation, but I do remember there being quite a few answers on StackOverflow of how I could accomplish this. I remember having a few issues with implementing a solution, but ultimately I was able to figure it out. Today I created a solution that works. Of course you can copy my code, tweak it to meet your needs, etc.

You can find the repository [here](https://github.com/JasonFritsche/angular-highlight-search-pipe). 

# Quick Rundown

I'll give you the full code snippet for the pipe and a rundown of how I used it.

## The Pipe

Here is the code for the pipe. 

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

@Pipe({
  name: 'highlightSearch',
})
export class HighlightSearchPipe implements PipeTransform {
  transform(value: any, args: any): any {
    if (!args) {
      return value;
    }

    const regex = new RegExp(args, 'gi');
    const match = value.match(regex);

    if (!match) {
      return value;
    }

    return value.replace(regex, `<span class='highlight'>${match[0]}</span>`);
  }
}
```
As you can see, I have a `highlight` class in the return value. I defined this class in the global `styles.scss` file like so:

```css
.highlight {
  background-color: violet;
  font-weight: bold;
}
```
## Implementation

### search-text Component

First I'll show you the important parts of the component, then I'll share the full template and code.

In my `search-text.component.html` template I use the pipe like so:
```html
  <p [innerHTML]="pet.description | highlightSearch: Search"></p>
```
You'll notice that `Search` is the value that is passed to the pipe. The `Search` value is set in the `OnSearched` method. In the same file, on line 1, I get my search term from the `searched` event emitter, which calls the `OnSearched` method and gives me the value.
```html
<app-search (searched)="OnSearched($event)"></app-search>
```

Here is the full `search-text.component.html` file:

```html
<app-search (searched)="OnSearched($event)"></app-search>
<div class="card-container">
  <div class="card" *ngFor="let pet of pets">
    <mat-card>
      <mat-card-header>
        <mat-card-title>{{ pet.name }}</mat-card-title>
        <mat-card-subtitle>{{ pet.species }}</mat-card-subtitle>
      </mat-card-header>
      <mat-card-content>
        <p [innerHTML]="pet.description | highlightSearch: Search"></p>
        <p>
          <strong>Nickname/s: </strong>
          <span *ngFor="let nickname of pet.nicknames; let i = index"
            >{{ nickname
            }}{{ i === pet.nicknames.length - 1 ? "" : ",&nbsp;" }}</span
          >
        </p>
      </mat-card-content>
    </mat-card>
  </div>
</div>
```

And here is the full `search-text.component.ts` file:

```javascript
import { Component, OnInit } from '@angular/core';
import * as data from './searchdata.json';

@Component({
  selector: 'app-search-text',
  templateUrl: './search-text.component.html',
  styleUrls: ['./search-text.component.scss'],
})
export class SearchTextComponent implements OnInit {
  public Search: string = null;
  public pets: any = (data as any).default;
  constructor() {}

  ngOnInit(): void {}

  public OnSearched(searchTerm: string) {
    this.Search = searchTerm;
  }
}
```

### search Component
Just like the search-text component, I'll give you the highlights first, then the full template and code.

In the search.component.html I get the input from the user like so:

```html
<input matInput (input)="onSearch($event.target.value)" />
```

Of course I will now show you the onSearch method:

```javascript
 public onSearch(searchTerm: string): void {
    this.searched.emit(searchTerm);
  }
```
The output property called `searched` looks like this:

```javascript
@Output() searched = new EventEmitter<string>();
```
As promised, here is the full `search.component.html` file:

```html
<mat-toolbar>
  <span>My Pets</span>
  <span class="spacer"></span>
  <mat-icon aria-hidden="false" aria-label="Example home icon">search</mat-icon>
  <mat-form-field class="form-field">
    <input matInput (input)="onSearch($event.target.value)" />
  </mat-form-field>
</mat-toolbar>
```

And here is the `search.component.ts` file:

```javascript
import { Component, OnInit, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-search',
  templateUrl: './search.component.html',
  styleUrls: ['./search.component.scss'],
})
export class SearchComponent implements OnInit {
  @Output() searched = new EventEmitter<string>();

  constructor() {}

  ngOnInit(): void {}

  public onSearch(searchTerm: string): void {
    this.searched.emit(searchTerm);
  }
}
```

# Conclusion
I hope you found this interesting or helpful. Let me know your thoughts. If you want to see the code, please view it [here](https://github.com/JasonFritsche/angular-highlight-search-pipe).