Highlighting a filtered result in AngularJS

前端 未结 13 2089
醉话见心
醉话见心 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, '$&'));
                    } 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, '$&'));
                            }
                            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, '$&'));
            }
            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.

提交回复
热议问题