Highlight search result using Angular filter

Highlighting search result improves the user experience and makes the search process less time consuming compare to showing the search result only.

We are very familiar with this feature, it is available in almost every browser, rich text editors and document processor like Google docs.

In this tutorial i am going to explain you how to develop the highlight feature using AngularJs filter module.

LIVE DEMO DOWNLOAD

Our approach to develop this system is straightforward. Filter module allows use to provide live search for the given data bind with $scope.

We will extend filter module to determine the way to extract the matched search phrases and then simply replace those matched phrases with span tag colored as green or something.

To extract search phrases from $scope data i used simple regular expression.

new RegExp('('+phrase+')', 'gi')

Code:

We are using simple HTML tags and filter module of angular to perform search. HTML code are placed in index.html and Angular code is in app.js.

index.html
<!DOCTYPE html>
<html>
  <head>
    <script src="angular.js"></script>
    <script src="app.js"></script>
    <style>
      .highlighted { background: yellow }
    </style>
  </head>

  <body ng-app="Demo">
    <h1>Highlight text using AngularJS.</h1>

    <div class="container" ng-controller="Demo">
      <input type="text" placeholder="Search" ng-model="search.text">

      <ul>
        <!-- filter code -->
        <div ng-repeat="item in data | filter:search.text"
           ng-bind-html="item.text | highlight:search.text">
        </div>
      </ul>
    </div>
  </body>
</html>

Here is our Angular code to highlight filter result.

app.js
angular.module('Demo', [])
  .controller('Demo', function($scope) {
    $scope.data = [
      { text: "<< ==== Put text to Search ===== >>" }
    ]
  })
  .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)
    }
  })

Explanation:

Observe code shown below. I am performing filter operation by binding textbox to it. So when you type anything in textbox, data present in $scope.data will be filter accordingly.

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

In angular code i extended filter module which returns the matched Search and if the input present in filter keyword is similar to the one filter found we will replace it with SPAN which in turn hold the matched search data placed in $1.

 if (phrase) text = text.replace(new RegExp('('+phrase+')', 'gi'),
        '<span class="highlighted">$1</span>')

Enhancement:

We can proceed with performing search on dynamic data and highlighting the found key. To do that you can use any backend technology like Node.js, PHP to perform database operation and bind the data in $scope variable.

Our code will work with whatever content present in $scope.data. You can either put static content on it or dynamic content depend upon your application.

You can use this code in web application such as text processor ( Like Google docs ) or any sort of search where your main goal is to help user find information quickly.

Further reading:

There is one rich library on angular called UI.UTILS which contains many GUI interaction code. Have a look on this.

External link : UI.UTILS home page.

Conclusion:

Highlighting a text so that user can quickly find it is really very powerful approach to improve interaction with your application. This small piece of code may help you to achieve or at least gives you a kick start !

Shahid (UnixRoot) Shaikh

Hey there, This is Shahid, an Engineer and Blogger from Bombay. I am also an Author and i wrote a programming book on Sails.js, MVC framework for Node.js.

Related Posts

7 Comments

  1. Hey – nice article. I’m an angular newb. I’m having trouble implementing this. Will this work if I’m pulling the text I want to search in using ajax from a local json file? Here is my code – any thoughts would be tremendously appreciated.

    Thanks,
    Rich

    //My controller
    var testControllers = angular.module(‘testControllers’, []);
    testControllers.controller(‘ListController’, [‘$scope’,’$http’, ‘$location’, function($scope, $http, $location) {
    $http.get(‘js/data.json’).success(function(data) {
    $scope.tests = data;

    $scope.filter(‘highlight’, function($sce) {
    return function(text, phrase) {
    if (phrase) text = text.replace(new RegExp(‘(‘+phrase+’)’, ‘gi’),
    ‘$1’)

    return $sce.trustAsHtml(text)
    }
    })
    });
    $scope.pageClass = ‘page-search’;
    $scope.pageTitle = ‘Information Center’;

    }]);

    //html
    div class=”search-container” ng-show=”showSection(1)”>


    Go To Test

    CPT Codes: {{test.cptCodes}}

  2. Nice concise and clean implementation, used this as basis for my needs to use one-or-more phrases to and an arbitrary tag, passing both the tag name and the phrases (one string or an array of strings) as arguments to the filter:

    (HTML tags below are missing brackets only so they don’t get filtered out of my comment, and in code sample, LT and GT placeholders are used)

    view:

    '
             div ng-bind-html="myForm.invited | tagmatch: 'rsvp' : myCtrl.confirmed"
             </div>

    filter:


    GeSHi Error: GeSHi could not find the language javscript (using path /var/www/html/wp-content/plugins/codecolorer/lib/geshi/) (code 2)

    sample inputs:

           model: myForm.invited // 'John Paul George Ringo'
           tagname: 'rsvp' // app.css: rsvp {font-weight: bold; }
           phrases: myCtrl.confirmed // ['Paul','Ringo']

    result (simplified):
    John rsvpPaul/rsvp George rsvpRingo/rsvp

    Obviously one can use a different wrapper for the matched phrases, but in my case, was simpler to just use an arbitrary HTML tag (also because I need to parse OUT that tag for a subsequent transformation, so simpler to go after a tag instead of a span-with-class combo)

    Performance does not seem to be a problem, but can probably be tuned further.

    (apologies if there’s a syntax error in the above after I sanitized my code for example-ness, but one gets the idea I hope … put angle brackets back in where appropriate, etc.)

  3. Hi, thanks for this, I know is an old post but it has help me so far, I’m trying to do something similar but with static content and highlighting x number of strings, I have an array with 2 strings, right now is only highlighting the first one (AngularJS), I will like both to be highlighted, my code is the following:

    HTML
    ——

    Highlight text using AngularJS.

    {{key}}

    JS
    —–
    angular.module(‘Demo’, [])
    .controller(‘Demo’, function($scope) {
    $scope.data = [
    { text: “AngularJS is a toolset for building the framework most suited to your application development. It is fully extensible and works well with other libraries. Every feature can be modified or replaced to suit your unique development workflow and feature needs. ” }
    ]
    $scope.keyWords = [‘AngularJS’,’toolset’];

    $scope.key = function(){
    for (var i in $scope.keyWords) {
    return $scope.keyWords[i];
    };
    }

    })
    .filter(‘highlight’, function($sce) {
    return function(text, phrase) {
    if (phrase) text = text.replace(new RegExp(‘(‘+phrase+’)’, ‘gi’),
    ‘$1’)

    return $sce.trustAsHtml(text)
    }
    })

  4. Hi,

    That’s a great implementation. One thing it messes up with is that if “number” filter is applied to the text and the phrase doesn’t contain “,”. e.g if the text value is 1,23,450 and the user has typed 123.
    Need to modify the regexp to have a “,” after every digit if the string is a number or is there any better workaround in Angular itself for this?

Leave a Reply

Your email address will not be published. Required fields are marked *