9

I have a controller that has an assigned value:

$scope.post = 'please visit http://stackoverflow.com quickly';

I have some text in my html:

<p>{{post}}</p>

I would like to make a clickable link of the url (surround it with anchor tags).

I tried to change my html to:

<p ng-bind-html="post | createAnchors"></p>

Here is a simplified example of the problem:

http://jsfiddle.net/T3fFt/4/

The question is, how can I escape the whole post text, except for the link, which will be surrounded by anchor tags? ?

Daan
  • 7,685
  • 5
  • 43
  • 52
  • Why is there no accepted answer for this question. At least one of these are Kato approved. Make it so. – Kato Jul 12 '14 at 22:20

2 Answers2

19

I think you can use Angular's linky filter for this: https://docs.angularjs.org/api/ngSanitize/filter/linky

You can use it like so:

<p ng-bind-html="post | linky"></p>

You'll have to include Angular's sanitize module for linky to work:

angular.module('myApp', [
    'ngRoute',
    'ngSanitize',
    'myApp.filters', 
    ...
exclsr
  • 3,329
  • 23
  • 27
  • I think the linky filter has been available since AngularJS 1.0: https://code.angularjs.org/1.0.2/docs/api/ngSanitize.filter:linky – exclsr Jul 18 '14 at 22:06
  • 1
    @Daan I'm on Angular v1.2.21 and it works fine. `
    `
    – GFoley83 Jan 22 '15 at 04:37
  • A word of warning to anyone wanting to use linkyFilter: It escapes HTML characters so your raw HTML code (but with links) will show up in the html-bound element – Dylanthepiguy Jul 05 '16 at 03:50
  • Yes, @Dylanthepiguy, that is the desired behavior for this question. – exclsr Jul 17 '16 at 08:24
1

You can use this replace for the string:

'please visit http://stackoverflow.com quickly'.replace(/(http[^\s]+)/, '<a href="$1">$1</a>')

then you'll need to use the $sce service, and ngBindHtml directive.

$sce is a service that provides Strict Contextual Escaping services to AngularJS.

So in your filter you need to wrap links with a tags then return a trusted html using $sce.trustAsHtml:

filter('createAnchors', function ($sce) {
    return function (str) {
        return $sce.trustAsHtml(str.
                                replace(/</g, '&lt;').
                                replace(/>/g, '&gt;').
                                replace(/(http[^\s]+)/g, '<a href="$1">$1</a>')
                               );
    }
})

Working examples: http://jsfiddle.net/T3fFt/11/

CD..
  • 72,281
  • 25
  • 154
  • 163
  • Can you please tell me what functions exactely? I tried a few of them but didn't get it to work. – Daan Jan 31 '14 at 09:07
  • did you try `trustAsHtml`? – CD.. Jan 31 '14 at 09:07
  • Do I get it right: When you set ng-bind-html, Angular will not escape html. When you then manually set $sce.trustAsHtml, this is the same right? So in that case that won't help me – Daan Jan 31 '14 at 09:11
  • The problem with this solution is that the rest of the text is not getting escaped. Check http://jsfiddle.net/T3fFt/5/ where another anchor is not escaped. I updated my question with a jsfiddle. – Daan Jan 31 '14 at 09:31
  • I've lost you, you do not want to escape the string? – CD.. Jan 31 '14 at 09:43
  • When someone enters a url in the post, I want them to get anchor tags around them and THAT anchor tag should not be escaped but rendered as HTML. The REST of the post should be escaped, so a user cannot insert – Daan Jan 31 '14 at 09:47
  • Yes like that, but than I don't want to escape every character myself (what you do now with the `replace(/ – Daan Jan 31 '14 at 10:18
  • No such function AFAIK. – CD.. Jan 31 '14 at 11:13