wake-up-neo.com

Hervorheben eines gefilterten Ergebnisses in AngularJS

Ich verwende einen ng-Wiederholungs- und Filtervorgang in angleJS wie das Tutorial für Telefone. Ich möchte jedoch die Suchergebnisse auf der Seite markieren. Mit Basic jQuery hätte ich einfach die Seite nach Taste auf der Eingabe analysiert, aber ich versuche es auf die eckige Art und Weise. Irgendwelche Ideen ?

Mein Code:

<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>
54
Lukmo

In tat das für 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;
}
85
Dmitri Algazin

winkelige ui-utils unterstützt nur einen Begriff. Ich verwende den folgenden Filter anstelle einer Bereichsfunktion:

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

Und das HTML:

<span ng-bind-html="theText | highlight:theTerms"></span>
21
Uri

Versuchen Sie Angular UI

Filter -> Highlite (Filter) . Es gibt auch die Keypress-Direktive.

13
Dmitry

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

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

8
Shaikh Shahid

Ich hoffe, mein Lichtbeispiel wird es leicht verständlich machen:

  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

5
mrded

Es gibt einen Standard-Highlight-Filter in der angle-bootstrap : typeaheadHighlight

Verwendungszweck

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

Mit Geltungsbereich {text:"Hello world", query:"world"} wird gerendert 

<span...>Hello <strong>world</strong></span>
5
user854301

Ich löste die Antwort von @ uri in diesem Thread und änderte sie, um mit einem einzelnen String ODER einem String-Array zu arbeiten.

Hier ist die 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);
};

Was bedeutet dies 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= {}));
;

Oder wenn Sie nur eine einfache JavaScript-Implementierung ohne diese generierten Namespaces wollen:

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

EDITIERTEUm einen Fix einzufügen, der zuvor defekt wäre, wird nach . oder einem anderen Zeichen gesucht, das in einem regulären Ausdruck eine Bedeutung hat. Jetzt werden diese Zeichen zuerst entkommen.

4
Chris Barr

Verwenden Sie ng-class, die angewendet wird, wenn der Suchbegriff sich auf die Daten bezieht, die das Element enthält.

Bei Ihren Wiederholungselementen hätten Sie ng-class="{ className: search_query==elementRelatedValue}"

dies würde die Klasse "className" dynamisch auf Elemente anwenden, wenn die Bedingung erfüllt ist.

Danke, dass Sie das gefragt haben, da es auch etwas war, mit dem ich mich gerade befasst habe.

Zwei Dinge jedoch:

Erstens, Die erste Antwort ist großartig, aber der Kommentar dazu ist richtig, dass highlight () Probleme mit Sonderzeichen hat. Dieser Kommentar schlägt vor, eine Escape-Kette zu verwenden, die funktionieren wird, aber sie schlägt vor, unescape () zu verwenden, das ausläuft. Was ich endete mit:

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

Zweitens habe ich versucht, dies in einer datengebundenen Liste von URLs zu tun. Während Sie sich in der highlight () - Zeichenfolge befinden, brauchen Sie keine Datenbindung.

Beispiel:

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

Wurden:

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

Ich hatte Probleme, wenn man sie in {{}} beließ und alle möglichen Fehler bekam.

Ich hoffe, das hilft jedem, der die gleichen Probleme hat.

0
mattjay

Über die Probleme mit speziellen Charakteren denke ich, dass Sie die Regex-Suche verlieren könnten. 

Was ist mit diesem:

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

Ein ungültiger regulärer Ausdruck könnte ein Benutzer sein, der nur den Text eingibt:

  • gültig: m
  • ungültig: m [
  • ungültig: m [ô
  • ungültig: m [ôo
  • gültig: m [ôo]
  • gültig: m [oo] n
  • gültig: m [oo] ni
  • gültig: m [ôo] nic
  • gültig: m [oo] nica

Was denkst du @Mik Cox?

0
Andre Medeiros

Meine Lösung für Highlight, verwendete dies mit einem eckigen UI-Baumelement: https://codepen.io/shnigi/pen/jKeaYG

angular.module('myApp').filter('highlightFilter', $sce =>
 function (element, searchInput) {
   element = element.replace(new RegExp(`(${searchInput})`, 'gi'),
             '<span class="highlighted">$&</span>');
   return $sce.trustAsHtml(element);
 });

Css hinzufügen:

.highlighted {
  color: orange;
}

HTML:

<p ng-repeat="person in persons | filter:search.value">
  <span ng-bind-html="person | highlightFilter:search.value"></span>
</p>

Und um eine Sucheingabe hinzuzufügen:

<input type="search" ng-model="search.value">
0
Shnigi

Ein anderer Vorschlag:

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

Ich bin offen für Kritik! ;-)

0
Monkey Monk

Wenn Sie die Winkelmaterialbibliothek verwenden, gibt es eine eingebaute Direktive namens md-highlight-text

Aus der Dokumentation:

<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 zu den Dokumenten: https://material.angularjs.org/latest/api/directive/mdHighlightText

0
Anthony