Highlighting a filtered result in AngularJS

前端 未结 13 2058
醉话见心
醉话见心 2020-12-01 00:12

I\'m using a ng-repeat and filter in angularJS like the phones tutorial but I\'d like to highlight the search results in the page. With basic jQuery I would have simply pars

相关标签:
13条回答
  • 2020-12-01 00:20

    Going off of @uri's answer in this thread, I modified it to work with a single string OR a string array.

    Here's the 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);
    };
    

    Which translates to this in 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 those 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 fix that would have previously broken this is someone searched for . or any other character that had meaning in a regular expression. Now those characters get escaped first.

    0 讨论(0)
  • 2020-12-01 00:20

    Another proposition:

    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'm open to criticism ! ;-)

    0 讨论(0)
  • 2020-12-01 00:26

    Try Angular UI

    Filters -> Highlite (filter). There is also Keypress directive.

    0 讨论(0)
  • 2020-12-01 00:26

    If you are using the 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 docs: https://material.angularjs.org/latest/api/directive/mdHighlightText

    0 讨论(0)
  • 2020-12-01 00:28

    In did that 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;
    }
    
    0 讨论(0)
  • 2020-12-01 00:30

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

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

    0 讨论(0)
提交回复
热议问题