0

I am using Angular JS to get and ng-repeat over Twitter tweets. I needed to highlight parts of the tweet string, like @tag and #hash, so it was suggested I use replace to add DOM wrappers around the things I want to highlight.

The issue is, since I'm not directly outputting to the DOM, and instead ng-repeating over a scope variable, the html tags don't seem to be added to the strings.

Question: How can I append html tags to a JS string?


Directive snippet:

scope.getTweets = function () {
    ModulesService.getTweets().success(function (res) {
        if (res && Array.isArray(res)) {
            scope.tweets = parseTweets(res);
        }
    });
};
scope.getTweets();
var parseTweets = function (tweets) {
    tweets.forEach(function (tweet) {
        tweet.text.replace(/(@[^ ]+)/g, '<a class="user">$1</a>').
        replace(/(#[^ ]+)/g, '<span class="hash">$1</span>').
        replace(/(https?:\/\/[^ ]+)/g, '<a href="$1">$1</a>');
        console.log('tweet!', tweet.text); //does not contain altered HTML
    });
    return tweets;
};

HTML:

<div ng-repeat="tweet in tweets" class="post-body clearfix">
    {{tweet.text}}
</div>
0

3 Answers 3

1

use filter like this

  filterExample.filter('filterName', function () {
    return function (text) {
    var str = text.replace(/(@[^ ]+)/g, '<a class="user">$1</a>').
    replace(/(#[^ ]+)/g, '<span class="hash">$1</span>').
    replace(/(https?:\/\/[^ ]+)/g, '<a href="$1">$1</a>');
        return str.toLowerCase();
    };
 })

and in html

  <div ng-repeat="tweet in tweets" class="post-body clearfix">
      <span ng-bind-html="tweet.text | filterName"></span>
    </div>
Sign up to request clarification or add additional context in comments.

3 Comments

This is great! Angular renders them as escaped. How can I unescape them so they render as HTML tags?
require to import the sanitize module and js file
There is no good reason to use a filter here; they run on every digest loop and can be a real drag on performance. Filters should only be used when the data is likely to change frequently enough to make that worthwhile -- in this case you'd be much better off pre-parsing the tweets as you were doing originally, rather than constantly re-running those regexes in a filter. Srinivasan A and OscarJ's answers (combined) would solve your issue without introducing performance problems.
1

Have you tried ng-bind-html?

 <div ng-repeat="tweet in tweets" class="post-body clearfix">
   <p ng-bind-html="tweet.text"></p>
</div>

Comments

1

Firstly, the replace method doesn't change the string but returns a new string with the replacements. Change your code to:

tweet.text = tweet.text.replace(...).replace(...)...;

Secondly {{tweet.text}} gets replaced by html escaped text. Change it to:

<span ng-bind-html="tweet.text"></span>

1 Comment

As per @Daniel's comment I've added @Srinivasan's solution to mine, except I used <span> rather than <p> as the latter generally has the side effect of adding white-space to the result as rendered by the browser.

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.