cloak angularjs angularjs-ng-repeat

cloak - Resaltando un resultado filtrado en AngularJS



ng-model (12)

Estoy usando un ng-repeat y filtro en angularJS como el tutorial de teléfonos, pero me gustaría destacar los resultados de búsqueda en la página. Con jQuery básico, simplemente habría analizado la página en la tecla de la entrada, pero estoy tratando de hacerlo de forma angular. Algunas ideas ?

Mi código :

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



Use ng-class que se aplica cuando el término de búsqueda está relacionado con los datos que contiene el elemento.

Entonces, en los elementos repetidos ng, tendrías ng-class="{ className: search_query==elementRelatedValue}"

que aplicaría la clase "className" a los elementos dinámicamente cuando se cumple la condición.


En hizo eso para 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; }


Sobre los problemas con el caracter especial, creo que escapándote podrías perder la búsqueda de expresiones regulares.

¿Qué tal esto?

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

Una expresión regular no válida podría ser usuario simplemente escribiendo el 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

¿Qué piensas @Mik Cox?


Otra proposición

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

¡Estoy abierto a la crítica! ;-)


Gracias por preguntar esto porque también era algo con lo que estaba lidiando.

Dos cosas sin embargo:

En primer lugar, la respuesta principal es excelente, pero el comentario es preciso que highlight () tiene problemas con los caracteres especiales. Ese comentario sugiere usar una cadena de escape que funcionará pero sugieren usar unescape () que se está eliminando. Lo que terminé con:

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

En segundo lugar, estaba tratando de hacer esto en una lista de URLs ligada a datos. Mientras está en la cadena de resaltado (), no necesita enlazar datos.

Ejemplo:

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

Convirtió:

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

Estaba teniendo problemas al dejarlos en {{}} y recibir todo tipo de errores.

Espero que esto ayude a cualquiera a encontrarse con los mismos problemas.


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

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


Ui-utils angular admite solo un término. Estoy usando el siguiente filtro en lugar de una función de alcance:

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

Y el HTML:

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


Hay un filtro de resaltado estándar en el arranque angular : typeaheadHighlight

Uso

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

Con el alcance {text:"Hello world", query:"world"} representa en

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


Saliendo de la respuesta de @uris en este hilo, lo modifiqué para que funcione con una sola cadena O una matriz de cadenas.

Aquí está la versión de 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://.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); };

Lo que se traduce a esto en 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://.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= {})); ;

O si solo desea una implementación simple de JavaScript sin esos espacios de nombres generados:

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

EDITADO para incluir una solución que previamente se hubiera roto, es alguien que ha buscado . o cualquier otro personaje que tenga significado en una expresión regular. Ahora esos personajes se escapan primero.


Espero que mi ejemplo de luz lo haga fácil de entender:

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>


Si está utilizando la biblioteca de materiales angulares, hay una directiva integrada llamada md-highlight-text

De la documentación:

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

Enlace a documentos: https://material.angularjs.org/latest/api/directive/mdHighlightText