Выделение отфильтрованного результата в AngularJS

angularjs angularjs-ng-repeat

56507 просмотра

13 ответа

Я использую ng-repeat и фильтр в angularJS, как в учебнике по телефонам, но я бы хотел выделить результаты поиска на странице. С базовым jQuery я бы просто проанализировал страницу при вводе, но я пытаюсь сделать это угловым путем. Есть идеи ?

Мой код:

<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>
Автор: Lukmo Источник Размещён: 12.11.2019 09:55

Ответы (13)


90 плюса

Решение

Сделал это для 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;
}
Автор: Dmitri Algazin Размещён: 24.04.2014 02:55

22 плюса

angular ui-utils поддерживает только один термин. Я использую следующий фильтр, а не функцию объема:

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

И HTML:

<span ng-bind-html="theText | highlight:theTerms"></span>
Автор: Uri Размещён: 17.08.2014 10:13

13 плюса

Попробуйте Angular UI

Фильтры -> Highlite (фильтр). Существует также директива Keypress.

Автор: Dmitry Размещён: 20.03.2013 09:42

8 плюса

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

Ссылка: http://codeforgeek.com/2014/12/highlight-search-result-angular-filter/ demo: http://demo.codeforgeek.com/highlight-angular/

Автор: Shaikh Shahid Размещён: 06.01.2015 12:22

5 плюса

В angular-bootstrap есть стандартный фильтр Highlight :typeaheadHighlight

использование

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

С областью {text:"Hello world", query:"world"}визуализации в

<span...>Hello <strong>world</strong></span>
Автор: user854301 Размещён: 28.10.2015 12:52

5 плюса

Я надеюсь, что мой легкий пример облегчит понимание:

  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>

введите описание изображения здесь

Автор: mrded Размещён: 21.11.2016 12:15

4 плюса

Исходя из ответа @ uri в этой теме, я изменил его, чтобы он работал с одной строкой ИЛИ массивом строк.

Вот версия TypeScript

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

Что переводит на это в 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= {}));
;

Или, если вы просто хотите простую реализацию JavaScript без этих сгенерированных пространств имен:

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

РЕДАКТИРОВАТЬ, чтобы включить исправление, которое ранее нарушало бы это - кто-то искал .или любой другой символ, который имел значение в регулярном выражении. Теперь эти персонажи убегают первыми.

Автор: CBarr Размещён: 28.07.2015 12:54

1 плюс

Используйте ng-класс, который применяется, когда поисковый термин связан с данными, которые содержит элемент.

Так что на ваших нг повторяющихся элементов, вы бы ng-class="{ className: search_query==elementRelatedValue}"

который будет применять класс "className" к элементам динамически при выполнении условия.

Автор: holographic-principle Размещён: 20.03.2013 09:41

1 плюс

Мое решение для выделения было использовано с элементом angular-ui-tree: 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:

.highlighted {
  color: orange;
}

HTML:

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

И добавить поисковый ввод:

<input type="search" ng-model="search.value">
Автор: Shnigi Размещён: 27.06.2018 12:06

0 плюса

Что касается проблем со специальным символом, я думаю, что если вы уйдете, вы можете потерять поиск регулярных выражений.

Как насчет этого:

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

Недопустимое регулярное выражение может быть пользователем, просто набрав текст:

  • действительный: м
  • неверно: m [
  • недействительно: m [ô
  • недействительно: m [ôo
  • действительный: m [ôo]
  • действительный: m [ôo] n
  • действительный: m [ôo] ni
  • действительный: м [ник]
  • действительный: m [ôo] nica

Как вы думаете, @Mik Cox?

Автор: Andre Medeiros Размещён: 24.05.2014 03:24

0 плюса

Другое предложение:

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

Я открыт для критики! ;-)

Автор: Monkey Monk Размещён: 01.10.2014 11:56

0 плюса

Спасибо, что спросили об этом, так как я тоже имел дело с этим.

Хотя две вещи:

Во-первых, верхний ответ отличный, но комментарий точный, что у highlight () есть проблема со специальными символами. В этом комментарии предлагается использовать экранирующую цепочку, которая будет работать, но они предлагают использовать unescape (), которая постепенно сокращается. Чем я закончил:

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

Во-вторых, я пытался сделать это в привязанном к данным списке URL-адресов. Находясь в строке highlight (), вам не нужно привязывать данные.

Пример:

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

стала:

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

Были проблемы с оставлением их в {{}} и получением всевозможных ошибок.

Надеюсь, что это помогает любому сталкиваться с теми же проблемами.

Автор: mattjay Размещён: 01.12.2014 12:52

0 плюса

Если вы используете библиотеку угловых материалов, есть встроенная директива под названием md-highlight-text

Из документации:

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

Ссылка на документы: https://material.angularjs.org/latest/api/directive/mdHighlightText

Автор: Anthony Размещён: 20.06.2017 05:07
Вопросы из категории :
32x32