Destacando um resultado filtrado no AngularJS

Eu estou usando um ng-repeat e filtro em angularJS como o tutorial de telefones, mas gostaria de destacar os resultados da pesquisa na página. Com o jQuery básico eu teria simplesmente analisado a página em cima da input, mas estou tentando fazer isso da maneira angular. Alguma ideia ?

Meu código:

  {{dci.marque}} ® {{dci.dci}}  

Em fez isso para AngularJS v1.2 +

HTML:

  

JS:

 $scope.highlight = function(text, search) { if (!search) { return $sce.trustAsHtml(text); } return $sce.trustAsHtml(text.replace(new RegExp(search, 'gi'), '$&')); }; 

CSS:

 .highlightedText { background: yellow; } 

O ui-utils angular suporta apenas um termo. Eu estou usando o seguinte filtro em vez de uma function de escopo:

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

E o HTML:

  

Tente a interface do usuário angular

Filtros -> Highlite (filtro). Há também a diretiva Keypress.

index.html

         

Highlight text using AngularJS.

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'), '$1') return $sce.trustAsHtml(text) } }) 

Referência: http://codeforgeek.com/2014/12/highlight-search-result-angular-filter/ demo: http://demo.codeforgeek.com/highlight-angular/

Há um filtro typeaheadHighlight Highlight no bootstrap angular : typeaheadHighlight

Uso

  

Com o escopo {text:"Hello world", query:"world"} processa em

 Hello world 

Espero que meu exemplo de luz facilite o entendimento:

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

   

insira a descrição da imagem aqui

Saindo da resposta do @uri nesse tópico, eu o modifiquei para trabalhar com uma única string OU uma matriz de strings.

Aqui está a versão do 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, '$&')); } else { return str; } }; } } angular .module("myApp") .filter("highlight", HighlightFilter); }; 

O que significa isso em 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= {})); ; 

Ou se você quiser apenas uma implementação JavaScript simples sem os namespaces gerados:

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

Editado para include uma correção que teria quebrado anteriormente isso é alguém procurado . ou qualquer outro personagem que tenha significado em uma expressão regular. Agora esses personagens escapam primeiro.

Use ng-class que é aplicado quando o termo de pesquisa está relacionado aos dados que o elemento contém.

Então, nos seus elementos repetidos, você teria ng-class="{ className: search_query==elementRelatedValue}"

que aplicaria a class “className” aos elementos dinamicamente quando a condição é atendida.

Sobre os problemas com caracter especial, acho que apenas escaping você pode perder a pesquisa de regex.

O que sobre isso:

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

Um regexp inválido poderia ser o usuário apenas digitando o texto:

  • válido: m
  • inválido: m [
  • inválido: m [ô
  • inválido: m [ôo
  • válido: m [ôo]
  • válido: m [ôo] n
  • válido: m [ôo] ni
  • válido: m [ôo] nic
  • válido: m [ôo] nica

O que você acha @Mik Cox?

Outra proposição:

 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 $('').append($(wrap).text(match)).html(); }); } return $sce.trustAsHtml(source); }; } // wrapText wrapText.$inject = ['$sce']; // use like this $filter('wrapText')('This is a word, really!', 'word', ''); // or like this {{ 'This is a word, really!' | wrapText:'word':'' }} 

Estou aberto a críticas! 😉

Obrigado por perguntar isso, pois era algo que eu estava lidando também.

Duas coisas embora:

Primeiro, a resposta principal é ótima, mas o comentário é preciso que highlight () tenha problema com caracteres especiais. Esse comentário sugere o uso de uma cadeia de escape que funcionará, mas eles sugerem usar o unescape () que está sendo eliminado. O que acabei com:

 $sce.trustAsHtml(decodeURI(escape(text).replace(new RegExp(escape(search), 'gi'), '$&'))); 

Em segundo lugar, eu estava tentando fazer isso em uma lista encadernada de dados de URLs. Enquanto na string highlight (), você não precisa vincular dados.

Exemplo:

 
  • {{item.headers.host}}{{item.url}}
  • Passou a ser:

      

    Estava tendo problemas para deixá-los em {{}} e recebendo todos os tipos de erros.

    Espero que isso ajude alguém a encontrar os mesmos problemas.

    Se você estiver usando a biblioteca de materiais angulares, existe uma diretiva md-highlight-text chamada md-highlight-text

    Da documentação:

      
    • {{result.text}}

    Link para documentos: https://material.angularjs.org/latest/api/directive/mdHighlightText

    Minha solução para destaque, usei isso com o elemento 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'), '$&'); return $sce.trustAsHtml(element); }); 

    Adicione css:

     .highlighted { color: orange; } 

    HTML:

     

    E para adicionar input de pesquisa: