最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS filter returning html as string - Stack Overflow

programmeradmin4浏览0评论

I've created an AngularJS filter to automatically create clickable links from addresses found in data. The filter:

app.filter('parseUrl', function() {
    var  //URLs starting with http://, https://, or ftp://
        replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim,
        //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
        replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim,
        //Change email addresses to mailto:: links.
        replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;

        return function(text, target, otherProp) {        
            angular.forEach(text.match(replacePattern1), function(url) {
                text = text.replace(replacePattern1, "<a href=\"$1\" target=\"_blank\">$1</a>");
            });
            angular.forEach(text.match(replacePattern2), function(url) {
                text = text.replace(replacePattern2, "$1<a href=\"http://$2\" target=\"_blank\">$2</a>");
            });
            angular.forEach(text.match(replacePattern3), function(url) {
                text = text.replace(replacePattern3, "<a href=\"mailto:$1\">$1</a>");
            });

            return text;        
        };
    });

And here is how I'm calling it (inside a paragraph):

<p><strong>Details:</strong> {{event.description | parseUrl}}</p>

And this works correctly to replace the plain text links with the code for a link. However, it replaces it with the link literally as plain text. For example, www.google would get replaced with &lt;a href="" target="_blank"&gt;;lt;/a&gt;. This clearly doesn't make a clickable link, which was my goal.

I'm not sure why this is happening. Any ideas on how to prevent/fix it? Thanks.

I've created an AngularJS filter to automatically create clickable links from addresses found in data. The filter:

app.filter('parseUrl', function() {
    var  //URLs starting with http://, https://, or ftp://
        replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim,
        //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
        replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim,
        //Change email addresses to mailto:: links.
        replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;

        return function(text, target, otherProp) {        
            angular.forEach(text.match(replacePattern1), function(url) {
                text = text.replace(replacePattern1, "<a href=\"$1\" target=\"_blank\">$1</a>");
            });
            angular.forEach(text.match(replacePattern2), function(url) {
                text = text.replace(replacePattern2, "$1<a href=\"http://$2\" target=\"_blank\">$2</a>");
            });
            angular.forEach(text.match(replacePattern3), function(url) {
                text = text.replace(replacePattern3, "<a href=\"mailto:$1\">$1</a>");
            });

            return text;        
        };
    });

And here is how I'm calling it (inside a paragraph):

<p><strong>Details:</strong> {{event.description | parseUrl}}</p>

And this works correctly to replace the plain text links with the code for a link. However, it replaces it with the link literally as plain text. For example, www.google. would get replaced with &lt;a href="http://www.google." target="_blank"&gt;http://google.&lt;/a&gt;. This clearly doesn't make a clickable link, which was my goal.

I'm not sure why this is happening. Any ideas on how to prevent/fix it? Thanks.

Share Improve this question asked Jul 10, 2013 at 1:42 JakemmarshJakemmarsh 4,67112 gold badges44 silver badges71 bronze badges 1
  • 1 You may want to take a look at the "linky" filter AngularJS provides (docs.angularjs/api/ngSanitize.filter:linky) in the ngSanitize module -- that filter may already do what you need, and the documentation for it supports the suggestions made in the answers regarding the ng-bind-html / ng-bind-html-unsafe directives. – CBerube Commented Jul 10, 2013 at 1:55
Add a ment  | 

3 Answers 3

Reset to default 7

Try using the ngBindHtmlUnsafe directive to have the HTML that your filter produces applied as actual innerHTML contents of an element, like so:

<span ng-bind-html-unsafe="event.description | parseUrl"></span>

You need to use either:

  • ngBindHtmlUnsafe
    If you 100% trust the source of the content
  • ngBindHtml
    If you don't trust the source of the content

Outputting a string using an expression will escape any html entities that you pass to it (symbols such as < > &)

I was using this filter for a while, somehow without noticing the disastrous results it produced. My modified version here:

filter('parseUrl', function($sce) {
var  //URLs starting with http://, https://, or ftp://
    replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim,
    //URLs starting with "www." (without // before it, or it'd re-link the ones done above).
    replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim,
    //Change email addresses to mailto:: links.
    replacePattern3 = /(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,6})/gim;

    return function(text, target, otherProp) {        
        text = (text + '').replace(/>/,"&gt;").replace(/</,"&lt;");
        text = (text + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br>$2');
        text = text.replace(replacePattern1, "<a href=\"$1\" target=\"_blank\">$1</a>");
        text = text.replace(replacePattern2, "<a href=\"http://$2\" target=\"_blank\">$2</a>");
        text = text.replace(replacePattern3, "<a href=\"mailto:$1\">$1</a>");
        return $sce.trustAsHtml(text);
    };
});

Notice that it's not using angular.forEach! (?????) The output would go ballistic when it did. Presumably this problem has to do with having multiple matches!

发布评论

评论列表(0)

  1. 暂无评论