Highlight the search text - angular 2

Building on a previous answer (HighlightedText-Component) I ended up with this:

import { Component, Input, OnChanges } from "@angular/core";

@Component({
    selector: 'highlighted-text',
    template: `
        <ng-container *ngFor="let match of result">
            <mark *ngIf="(match === needle); else nomatch">{{match}}</mark>
            <ng-template #nomatch>{{match}}</ng-template>
        </ng-container>
    `,
})
export class HighlightedTextComponent implements OnChanges {
    @Input() needle: string;
    @Input() haystack: string;
    public result: string[];

    ngOnChanges() {
        const regEx = new RegExp('(' + this.needle + ')', 'i');
        this.result = this.haystack.split(regEx);
    }
}

This way also multiple matches of the needle are highlighted. The usage of this component is similar to the one in the previous answer:

<highlighted-text [needle]="searchInput" [haystack]="value"></highlighted-text>

For me this approach using a component feels more secure, since I do not have to use "innerHtml".


You can do that by creating a pipe and applying that pipe to the summary part of array inside ngfor. Here is the code for Pipe:

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

@Pipe({
    name: 'highlight'
})

export class HighlightSearch implements PipeTransform {

    transform(value: any, args: any): any {
        if (!args) {return value;}
        var re = new RegExp(args, 'gi'); //'gi' for case insensitive and can use 'g' if you want the search to be case sensitive.
        return value.replace(re, "<mark>$&</mark>");
    }
}

and then in markup apply it on a string like this:

<div innerHTML="{{ str | highlight : 'search'}}"></div>

Replace 'search' with the word you want to highlight.

Hope this will help.


The selected answer has the following issues:

  1. It will return undefined if there is nothing provided in the search string
  2. The search should be case insensitive but that should not replace the original string case.

i would suggest the following code instead

transform(value: string, args: string): any {
    if (args && value) {
        let startIndex = value.toLowerCase().indexOf(args.toLowerCase());
        if (startIndex != -1) {
            let endLength = args.length;
            let matchingString = value.substr(startIndex, endLength);
            return value.replace(matchingString, "<mark>" + matchingString + "</mark>");
        }

    }
    return value;
}

If you have multiple words in your string than use pipe which accepts array and highlight each word in result.

You can use following pipe for multiple search words:-

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

@Pipe({
    name: 'highlight'
})

export class HighlightText implements PipeTransform {

    transform(value: any, args: any): any {
        if (!args) {return value;}
        for(const text of args) {
            var reText = new RegExp(text, 'gi');
            value = value.replace(reText, "<mark>" + text + "</mark>");
            //for your custom css
            // value = value.replace(reText, "<span class='highlight-search-text'>" + text + "</span>"); 


        }
        return value;
    }
}

Split you string to generate array of strings.

var searchTerms = searchKey.split(' ');

usage:

<div [innerHTML]="result | highlight:searchTerms"></div>

If you wanted to use custom class :

.highlight-search-text {
  color: black;
  font-weight: 600;
}

All the best!