8

I'm trying to write a set of filters to highlight and then dehighlight dynamically generated html:

Highlight filter:

app.filter('highlight', function ($sce) {
    return function (str, termsToHighlight) {
        // Sort terms by length
        termsToHighlight.sort(function (a, b) {
            return b.length - a.length;
        });
        var regex = new RegExp('(' + termsToHighlight.join('|') + ')', 'g');
        return $sce.trustAsHtml(str.toString().replace(regex, '<span class="highlightedSpan" style="background-color: yellow; ' +
            'font-weight: bold;">$&</span>'));
    };
});

Dehighlight:

app.filter('dehighlight', function ($sce) {
    return function (str) {

        var obj = $($.parseHTML(str));

        obj = obj.find('.highlightedSpan').replaceWith(function () { return this.innerHTML; });

        return $sce.trustAsHtml(obj.html());
    };
});

I'm trying to strip away the span tag and leave the original text, but I'm not sure if it's working or what to return. Str is the html string. Any help would be greatly appreciated!

4
  • Are you sure this is Angular2 or later? Commented Nov 20, 2017 at 16:19
  • @Gunter Angular 1.6 Commented Nov 20, 2017 at 16:24
  • 1
    angularjs is the correct tag for AngularJS 1.x. The angular tag is for Angular 2+ only. Using the correct tags increases chances to get a good answer. Commented Nov 20, 2017 at 16:25
  • 1
    How are you applying this filter? What's the actual problem? Is the text highlighted? Commented Nov 20, 2017 at 16:37

2 Answers 2

3
+25

We found marking terms with Angular to be a non-trivial task and ended up using an outside library (Mark.js). Manipulating the html directly like that can break angular's scoping and create other issues. If each possible term is in it's own little html tag, then you can use a filter on each one to test against a shared list of terms (either passed in or as part of a service), just remember that the "filter" is finicky about what changing inputs will fire a dirty-check and re-evaluate.

Sign up to request clarification or add additional context in comments.

2 Comments

Interesting, this looks like it'll work, but I need to do it my way because I'm going to re-use the filters to do linking/delinking of the found matches later. Namely I need to control what I inject / strip, which the library abstracts out.
You may have more luck using a directive with transclusion then. They are pretty tricky, but allow a lot more direct html manipulation.
2

Just for completeness sake, I got it in the end, the find function was misbehaving from my POV.

Final solution for dehighlighting:

app.filter('dehighlight', function () {
    return function (str) {
        var obj = $('<div/>').append(str);

        obj.find('span.highlightedSpan').replaceWith(function () { return this.innerHTML; });

        return obj.html().toString();
    };
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.