Highlighting a filtered result in AngularJS

I use ng-repeat and a filter in angularJS, as in the tutorial on phones, but I want to highlight the search results on the page. With basic jQuery, I would just parse the page with the key in, but I'm trying to do it in an angular way. Any ideas?

My code is:

<input id="search" type="text" placeholder="Recherche DCI" ng-model="search_query" autofocus> <tr ng-repeat="dci in dcis | filter:search_query"> <td class='marque'>{{dci.marque}} ®</td> <td class="dci">{{dci.dci}}</td> </tr> 
+50
angularjs angularjs-ng-repeat
Mar 20 '13 at 9:30
source share
12 answers

In did it for AngularJS v1.2 +

HTML:

 <span ng-bind-html="highlight(textToSearchThrough, searchText)"></span> 

JS:

 $scope.highlight = function(text, search) { if (!search) { return $sce.trustAsHtml(text); } return $sce.trustAsHtml(text.replace(new RegExp(search, 'gi'), '<span class="highlightedText">$&</span>')); }; 

CSS

 .highlightedText { background: yellow; } 
+79
Apr 24 '14 at
source share

angular ui-utils supports only one term. I use the following filter, not the scope function:

 app.filter('highlight', function($sce) { return function(str, termsToHighlight) { // Sort terms by length termsToHighlight.sort(function(a, b) { return b.length - a.length; }); // Regex to simultaneously replace terms var regex = new RegExp('(' + termsToHighlight.join('|') + ')', 'g'); return $sce.trustAsHtml(str.replace(regex, '<span class="match">$&</span>')); }; }); 

And HTML:

 <span ng-bind-html="theText | highlight:theTerms"></span> 
+19
Aug 17 '14 at 10:13
source share

Try Angular UI

Filters → Highlite (filter). There is also a Keypress directive.

+13
Mar 20 '13 at 9:42 on
source share

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> 

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) } }) 

Link: http://codeforgeek.com/2014/12/highlight-search-result-angular-filter/ demo: http://demo.codeforgeek.com/highlight-angular/

+5
Jan 06 '15 at 12:22
source share

Disabling the @uri response in this thread, I changed it to work with a single string OR a string array.

Here is TypeScript version

 module myApp.Filters.Highlight { "use strict"; class HighlightFilter { //This will wrap matching search terms with an element to visually highlight strings //Usage: {{fullString | highlight:'partial string'}} //Usage: {{fullString | highlight:['partial', 'string, 'example']}} static $inject = ["$sce"]; constructor($sce: angular.ISCEService) { // The `terms` could be a string, or an array of strings, so we have to use the `any` type here /* tslint:disable: no-any */ return (str: string, terms: any) => { /* tslint:enable */ if (terms) { let allTermsRegexStr: string; if (typeof terms === "string") { allTermsRegexStr = terms; } else { //assume a string array // Sort array by length then join with regex pipe separator allTermsRegexStr = terms.sort((a: string, b: string) => b.length - a.length).join('|'); } //Escape characters that have meaning in regular expressions //via: http://stackoverflow.com/a/6969486/79677 allTermsRegexStr = allTermsRegexStr.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); // Regex to simultaneously replace terms - case insensitive! var regex = new RegExp('(' + allTermsRegexStr + ')', 'ig'); return $sce.trustAsHtml(str.replace(regex, '<mark class="highlight">$&</mark>')); } else { return str; } }; } } angular .module("myApp") .filter("highlight", HighlightFilter); }; 

What translates to JavaScript :

 var myApp; (function (myApp) { var Filters; (function (Filters) { var Highlight; (function (Highlight) { "use strict"; var HighlightFilter = (function () { function HighlightFilter($sce) { // The `terms` could be a string, or an array of strings, so we have to use the `any` type here /* tslint:disable: no-any */ return function (str, terms) { /* tslint:enable */ if (terms) { var allTermsRegexStr; if (typeof terms === "string") { allTermsRegexStr = terms; } else { // Sort array by length then join with regex pipe separator allTermsRegexStr = terms.sort(function (a, b) { return b.length - a.length; }).join('|'); } //Escape characters that have meaning in regular expressions //via: http://stackoverflow.com/a/6969486/79677 allTermsRegexStr = allTermsRegexStr.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); // Regex to simultaneously replace terms - case insensitive! var regex = new RegExp('(' + allTermsRegexStr + ')', 'ig'); return $sce.trustAsHtml(str.replace(regex, '<mark class="highlight">$&</mark>')); } else { return str; } }; } //This will wrap matching search terms with an element to visually highlight strings //Usage: {{fullString | highlight:'partial string'}} //Usage: {{fullString | highlight:['partial', 'string, 'example']}} HighlightFilter.$inject = ["$sce"]; return HighlightFilter; })(); angular.module("myApp").filter("highlight", HighlightFilter); })(Highlight = Filters.Highlight || (Filters.Highlight = {})); })(Filters = myApp.Filters || (myApp.Filters = {})); })(myApp|| (myApp= {})); ; 



Or if you just want a simple JavaScript implementation without these generated namespaces:

 app.filter('highlight', ['$sce', function($sce) { return function (str, terms) { if (terms) { var allTermsRegexStr; if (typeof terms === "string") { allTermsRegexStr = terms; } else { // Sort array by length then join with regex pipe separator allTermsRegexStr = terms.sort(function (a, b) { return b.length - a.length; }).join('|'); } //Escape characters that have meaning in regular expressions //via: http://stackoverflow.com/a/6969486/79677 allTermsRegexStr = allTermsRegexStr.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); // Regex to simultaneously replace terms - case insensitive! var regex = new RegExp('(' + allTermsRegexStr + ')', 'ig'); return $sce.trustAsHtml(str.replace(regex, '<mark class="highlight">$&</mark>')); } else { return str; } }; }]); 

EDITED to include a patch that was previously broken, someone was looking for it . or any other character that matters in a regular expression. Now these characters are escaped first.

+4
Jul 28 '15 at 12:54
source share

Hope my easy example will facilitate understanding:

  app.filter('highlight', function() { return function(text, phrase) { return phrase ? text.replace(new RegExp('('+phrase+')', 'gi'), '<kbd>$1</kbd>') : text; }; }); 



  <input type="text" ng-model="search.$"> <ul> <li ng-repeat="item in items | filter:search"> <div ng-bind-html="item | highlight:search.$"></div> </li> </ul> 



enter image description here

+4
Nov 21 '16 at 12:15
source share

There is a standard Highlight filter in angular-bootstrap : typeaheadHighlight

Using

 <span ng-bind-html="text | typeaheadHighlight:query"></span> 

With the scope {text:"Hello world", query:"world"} appears in

 <span...>Hello <strong>world</strong></span> 
+3
Oct 28 '15 at 12:52
source share

Use the ng class, which is used when the search term is associated with the data contained in the element.

So on your ng-repeated elements you should have ng-class="{ className: search_query==elementRelatedValue}"

which will apply the class "className" to elements dynamically when the condition is met.

+1
Mar 20 '13 at 9:41
source share

About the problems with the special caracter, I think that just running away from you might lose the search in regular expression.

How about this:

 function(text, search) { if (!search || (search && search.length < 3)) { return $sce.trustAsHtml(text); } regexp = ''; try { regexp = new RegExp(search, 'gi'); } catch(e) { return $sce.trustAsHtml(text); } return $sce.trustAsHtml(text.replace(regexp, '<span class="highlight">$&</span>')); }; 

An invalid regular expression might be a user simply entering text:

  • valid: m
  • wrong: m [
  • invalid: m [ô
  • wrong: m [ôo
  • valid: m [ôo]
  • valid: m [ôo] n
  • valid: m [ôo] ni
  • valid: m [ôo] nic
  • valid: m [ôo] nica

What do you think @Mik Cox?

0
May 24 '14 at 15:24
source share

Another suggestion:

 app.filter('wrapText', wrapText); function wrapText($sce) { return function (source, needle, wrap) { var regex; if (typeof needle === 'string') { regex = new RegExp(needle, "gi"); } else { regex = needle; } if (source.match(regex)) { source = source.replace(regex, function (match) { return $('<i></i>').append($(wrap).text(match)).html(); }); } return $sce.trustAsHtml(source); }; } // wrapText wrapText.$inject = ['$sce']; // use like this $filter('wrapText')('This is a word, really!', 'word', '<span class="highlight"></span>'); // or like this {{ 'This is a word, really!' | wrapText:'word':'<span class="highlight"></span>' }} 

I am open to criticism !; -)

0
01 Oct '14 at 11:56 on
source share

Thanks for asking about this, as I dealt with this too.

Two things:

Firstly, the top answer is great, but the comment on it is correct that the highlight () function has problems with special characters. This comment suggests using an accelerating chain that will work, but they suggest using unescape (), which is phasing out. What I finished:

 $sce.trustAsHtml(decodeURI(escape(text).replace(new RegExp(escape(search), 'gi'), '<span class="highlightedText">$&</span>'))); 

Secondly, I tried to do this in a list of data-bound URLs. Although in the highlight () line you don't need to bind the data.

Example:

 <li>{{item.headers.host}}{{item.url}}</li> 

Became:

 <span ng-bind-html="highlight(item.headers.host+item.url, item.match)"></span> 

There was a problem with leaving them in {{}} and getting all kinds of errors.

Hope this helps anyone facing the same problems.

0
Dec 01
source share

If you are using angular material library, there is a built-in directive called md-highlight-text

From the documentation:

 <input placeholder="Enter a search term..." ng-model="searchTerm" type="text"> <ul> <li ng-repeat="result in results" md-highlight-text="searchTerm"> {{result.text}} </li> </ul> 

Link to documents: https://material.angularjs.org/latest/api/directive/mdHighlightText

0
Jun 20 '17 at 17:07 on
source share



All Articles