mark search string dynamically using angular.js

All we need is an easy explanation of the problem, so here it is.

How can I mark my search pattern dynamically in my html?
Example:

SearchExample

I’m using angular and my html looks like this:

<div>
   <input type="text" ng-model="viewmodel.searchString"/>
   <!--Moving over all phrases-->
   <div ng-repeat="phrase in viewmodel.Phrases">
        {{phrase.title}}            
   </div>
</div>

I want the string matching pattern will be mark on every change in search string.

Can you help me?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Angular UI is a great choice. You can also do it with filter like: http://embed.plnkr.co/XbCsxmfrgmdtOAeBZPUp/preview

The essence is as commented by @Hylianpuffball, dynamically create styled ‘span’ tags for the matches.

.filter('highlight', function($sce) {
  return function(text, phrase) {
    if (phrase) text = text.replace(new RegExp('('+phrase+')', 'gi'),
      '<span class="highlighted">$1</span>')

    return $sce.trustAsHtml(text)
  }
})

And use it like:

<li ng-repeat="item in data | filter:search.title"
    ng-bind-html="item.title | highlight:search.title">
</li>

Method 2

Just in case that someone (like me a moment ago) needs this for angular2:

highlight-pipe.ts:

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

@Pipe({name: 'highlightPipe'})
export class HighlightPipe implements PipeTransform{

  transform(text:string, filter:string) : any{
    if(filter){
      text = text.replace(new RegExp('('+filter+')', 'gi'), '<span class="highlighted">$1</span>');
    }
    return text;
  }
}

and use it like this:

at top of file:

import {HighlightPipe} from './highlight-pipe';

in template where ‘yourText‘ is the original text and ‘filter‘ is the part you want to highlight:

<div [innerHTML]="yourText | highlightPipe: filter"/>

in component:

pipes: [HighlightPipe]

EDIT:
I updated it for RC 4
and created a plunker for testing:
http://plnkr.co/edit/SeNsuwFUUqZIHllP9nT0?p=preview

Method 3

Try Angular UI

They have a highlight directive. You can use it as a reference to make your own (or just use it directly).

Method 4

Inspired by @tungd’s answer but valid for multiple search terms.

.filter('highlight', function($sce) {
  return function(text, phrase) {
    if (phrase){
        phrases = phrase.split(" ");
        for(i=0;i<phrases.length;i++)
            text = text.replace(new RegExp('('+phrases[i]+')', 'gi'),'~~~~~$1%%%%%')

        text = text.replace(new RegExp('('+'~~~~~'+')', 'gi'),'<span class="bold greenTxt">');
        text = text.replace(new RegExp('('+'%%%%%'+')', 'gi'),'</span>')      
    } 
    return $sce.trustAsHtml(text)
  }
});

PS: One can always limit the input to be in non-special chars for this to be 100% bullet-proof.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply