AngularJS filter returns html as string

I created an AngularJS filter to automatically create interactive links from the addresses found in the data. 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 what I call it (inside the paragraph):

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

And it works correctly to replace simple text links with code for the link. However, it replaces it with a link literally like plain text. For example, www.google.com is replaced by &lt;a href="http://www.google.com" target="_blank"&gt;http://google.com&lt;/a&gt; . This clearly does not make the clickable link, which was my goal.

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

+7
javascript angularjs angularjs-filter
source share
3 answers

Try using the ngBindHtmlUnsafe directive so that the HTML code that your filter creates as the actual innerHTML content of the element, for example

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

You need to use either:

Outputting a string using an expression will delete any html objects that you pass to it (characters such as <> &)

+2
source share

I used this filter for a while, one way or another, without noticing the disastrous results that it produced. The modified version is 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); }; }); 

Please note that it does not use angular.forEach! (?????) The exit would be ballistic when he did. Presumably this issue is due to having multiple matches!

+1
source share

All Articles