Skip to content

Instantly share code, notes, and snippets.

@adamrecsko
Created May 1, 2016 20:28
Show Gist options
  • Star 50 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save adamrecsko/0f28f474eca63e0279455476cc11eca7 to your computer and use it in GitHub Desktop.
Save adamrecsko/0f28f474eca63e0279455476cc11eca7 to your computer and use it in GitHub Desktop.
Angular2 text highlight pipe
import {PipeTransform, Pipe} from 'angular2/core';
@Pipe({ name: 'highlight' })
export class HighLightPipe implements PipeTransform {
transform(text: string, [search]): string {
return search ? text.replace(new RegExp(search, 'i'), `<span class="highlight">${search}</span>`) : text;
}
}
/** Usage:
* <input type="text" [(ngModel)]="filter">
* <div [innerHTML]="myAwesomeText | highlight : filter"></div>
*
*/
@ma7moud-abdallah
Copy link

how can i do it without splitting the text to two parts, i need the matched pattern get the style in it's same position of the original text

@ankitgrover
Copy link

Below is the implementation which enables you to do a little more things:

  1. Highlight single match, global match, single match which starts with search string.
  2. Make the matching case sensitive.
  3. Pass a highlighting style class.

Implementation:

import {Pipe, PipeTransform} from "@angular/core";
import {SafeHtml} from "@angular/platform-browser";

@pipe({ name: "highlightText" })
export class HighlightPipe implements PipeTransform {

/* use this for single match search */
static SINGLE_MATCH:string = "Single-Match";
/* use this for single match search with a restriction that target should start with search string */
static SINGLE_AND_STARTS_WITH_MATCH:string = "Single-And-StartsWith-Match";
/* use this for global search */
static MULTI_MATCH:string = "Multi-Match";

constructor() {
}
transform(data: string,
          highlightText: string,
          option:string = "Single-And-StartsWith-Match",
          caseSensitive:boolean = false,
          highlightStyleName:string = "search-highlight"): SafeHtml {
    if (highlightText && data && option) {
        let regex:any = "";
        let caseFlag:string = !caseSensitive ? "i" : "";
        switch (option) {
            case "Single-Match": {
                regex = new RegExp(highlightText, caseFlag);
                break;
            }
            case "Single-And-StartsWith-Match": {
                regex = new RegExp("^" + highlightText, caseFlag);
                break;
            }
            case "Multi-Match": {
                regex = new RegExp(highlightText, "g" + caseFlag);
                break;
            }
            default: {
                // default will be a global case-insensitive match
                regex = new RegExp(highlightText, "gi");
            }
        }
        return data.replace(regex, (match) => `<span class="${highlightStyleName}">${match}</span>`);

    } else {
        return data;
    }
}

}

@calebeaires
Copy link

Great, but how can I add an event click to this highlighted text after it is rendered into innerhtml?

@wuenping
Copy link

this regex pattern mean what? thanks

@andreevsm
Copy link

This code is not quite correct. For example:

input - xaxa
users: [ 'xaxalololo', 'nonoxaxaxaxa', 'wtfxaxaxaxaxaxa' ]

Should works only to first occurrence, the code below is correct:

const regex = new RegExp(`${pattern}(.*?)`, 'i');

After that:
users: [ 'xaxalololo', 'nonoxaxaxaxa', 'wtfxaxaxaxaxaxa' ]

@rafcontreras
Copy link

rafcontreras commented May 15, 2019

In case someone is having problems with @ankitgrover 's code (Thank you!) :

import { Pipe, PipeTransform } from "@angular/core";
import { SafeHtml } from "@angular/platform-browser";

@Pipe({ name: "highlightText" })
export class HighlightPipe implements PipeTransform {
    /* use this for single match search */
    static SINGLE_MATCH: string = "Single-Match";
    /* use this for single match search with a restriction that target should start with search string */
    static SINGLE_AND_STARTS_WITH_MATCH: string = "Single-And-StartsWith-Match";
    /* use this for global search */
    static MULTI_MATCH: string = "Multi-Match";

    constructor() {}
    transform(
        contentString: string = null,
        stringToHighlight: string = null,
        option: string = "Single-And-StartsWith-Match",
        caseSensitive: boolean = false,
        highlightStyleName: string = "search-highlight"
    ): SafeHtml {
        if (stringToHighlight && contentString && option) {
            let regex: any = "";
            let caseFlag: string = !caseSensitive ? "i" : "";
            switch (option) {
                case "Single-Match": {
                    regex = new RegExp(stringToHighlight, caseFlag);
                    break;
                }
                case "Single-And-StartsWith-Match": {
                    regex = new RegExp("^" + stringToHighlight, caseFlag);
                    break;
                }
                case "Multi-Match": {
                    regex = new RegExp(stringToHighlight, "g" + caseFlag);
                    break;
                }
                default: {
                    // default will be a global case-insensitive match
                    regex = new RegExp(stringToHighlight, "gi");
                }
            }
            const replaced = contentString.replace(
                regex,
                (match) => `<span class="${highlightStyleName}">${match}</span>`
            );
            return replaced;
        } else {
            return contentString;
        }
    }
}

@rafcontreras
Copy link

rafcontreras commented May 15, 2019

Usage:

<div [innerHTML]="
  string
    | highlightText
      : string
      : 'string'
      : boolean
      : 'string'
"></div>
<td>
  <div [innerHTML]="
    row.content
    | highlightText
      : searchInputValue
      : 'MULTI_MATCH'
      : true
      : 'your-class'
  "></div>
</td>

@Superkarl
Copy link

@rafcontreras use this, so you can search for special characters too:
stringToHighlight = stringToHighlight.replace(/([-[\]{}()*+?.\\^$|#,])/g,'\\$1');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment