This is my first Angular Directive.
I am trying to do a simple highlight on a html content based on the search terms used to find that content.
The problem is, that is working for the first term, but not for more. I want to all words get highlighted but I am doing something wrong when I replace the HTML content.
This is what the directive tries to do:
1. The directive should highlight one or more words. For example. If the search terms are "document legal" it should highlight both of them, even if they are not on this order.
So, a text like "legal something document" should get both highlighted, "legal" and "document".
2. If the word is less than 3 characters is not going to get highlighted.
3. If the word is not found, try removing the last character from it until its length is less than 3. You may search for "dimensions" and the search engine may return a text containing "dimension" or even "dime".
Just in case, the app is an Ionic App.
This is my code.
The angular directive:
angular.module('starter.directives', [])
.directive('highlightSearchTerms', function($compile) {
return {
restrict: 'A',
scope: true,
link: function($scope, element, attrs) {
$scope.highlightTerm = function(term) {
var html = element.html();
var highlighted = html.replace(new RegExp(term, 'gi'),
'<span class="highlightedText">$&</span>');
if (highlighted == null) {
return false;
}
// @see
// I think that the problem is here, it works the
// first time, but the second time it gets here
// the following exception is throwed
// "Cannot read property 'replaceChild' of null"
element.replaceWith(highlighted);
return html != highlighted;
};
var searchTerms = $scope.searchTerms;
if (searchTerms != undefined && searchTerms.length < 3) {
return;
}
var terms = searchTerms.split(' ');
// Try to highlight each term unless the word
// is less than 3 characters
for (var i = 0; i < terms.length; i++) {
var term = terms[i];
// // Try to highlight unless the word is less than 3 chars
while (term.length > 2) {
// If it got highlighted skip to next term
// else remove a character from the term and try again
if ($scope.highlightTerm(term)) {
break;
}
term = term.substring(0, term.length - 1);
}
}
}
};
});
You can see some weird things. Like using $scope.highlightTerm instead of passing the highlightTerm var to the directive. I couldn't get it work.
How can I change the HTML of the element correctly?
This is the template that is using the directive:
<div ng-include src="tplName" highlight-search-terms></div>
I wish to do something like that but I couldn't get it working:
<div ng-include src="tplName" highlight-search-terms="something to highlight"></div>
Here is a Plunker: http://plnkr.co/edit/BUDzFaTnxTdKqK5JfH0U?p=preview
$compileservice. I'm pretty certain you can break any bindings you may have in that HTML using just jquery.var html = element.html();always returns the same value since you're not recompiling after the replacement. Punov's solution works but it uses native Javascript to bypass angular, I don't know if we always want that.