How would I create a directive in angularjs that for example takes this element:
<div>Example text http://example.com</div>
And convert it in to this
<div>Example text <a href="http://example.com">http://example.com</a></div>
I already have the functionality written to auto link the text in a function and return the html (let's call the function "autoLink" ) but i'm not up to scratch on my directives.
I would also like to add a attribute to the element to pass a object in to the directive. e.g.
<div linkprops="link.props" >Example text http://example.com</div>
Where link.props is object like {a: 'bla bla', b: 'waa waa'} which is to be passed to the autoLink function as a second param (the first been the text).
Two ways of doing it:
app.directive('parseUrl', function () {
    var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/gi;
    return {
        restrict: 'A',
        require: 'ngModel',
        replace: true,
        scope: {
            props: '=parseUrl',
            ngModel: '=ngModel'
        },
        link: function compile(scope, element, attrs, controller) {
            scope.$watch('ngModel', function (value) {
                var html = value.replace(urlPattern, '<a target="' + scope.props.target + '" href="$&">$&</a>') + " | " + scope.props.otherProp;
                element.html(html);
            });
        }
    };
});
HTML:
<p parse-url="props" ng-model="text"></p>
app.filter('parseUrlFilter', function () {
    var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/gi;
    return function (text, target, otherProp) {
        return text.replace(urlPattern, '<a target="' + target + '" href="$&">$&</a>') + " | " + otherProp;
    };
});
HTML:
<p ng-bind-html-unsafe="text | parseUrlFilter:'_blank':'otherProperty'"></p>
Note: The 'otherProperty' is just for example, in case you want to pass more properties into the filter.
jsFiddle
Update: Improved replacing algorithm.
To answer the first half of this question, without the additional property requirement, one can use Angular's linky filter: https://docs.angularjs.org/api/ngSanitize/filter/linky
The top voted answer does not work if there are multiple links. Linky already does 90% of the work for us, the only problem is that it sanitizes the html thus removing html/newlines. My solution was to just edit the linky filter (below is Angular 1.2.19) to not sanitize the input.
app.filter('linkyUnsanitized', ['$sanitize', function($sanitize) {
  var LINKY_URL_REGEXP =
        /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/,
      MAILTO_REGEXP = /^mailto:/;
  return function(text, target) {
    if (!text) return text;
    var match;
    var raw = text;
    var html = [];
    var url;
    var i;
    while ((match = raw.match(LINKY_URL_REGEXP))) {
      // We can not end in these as they are sometimes found at the end of the sentence
      url = match[0];
      // if we did not match ftp/http/mailto then assume mailto
      if (match[2] == match[3]) url = 'mailto:' + url;
      i = match.index;
      addText(raw.substr(0, i));
      addLink(url, match[0].replace(MAILTO_REGEXP, ''));
      raw = raw.substring(i + match[0].length);
    }
    addText(raw);
    return html.join('');
    function addText(text) {
      if (!text) {
        return;
      }
      html.push(text);
    }
    function addLink(url, text) {
      html.push('<a ');
      if (angular.isDefined(target)) {
        html.push('target="');
        html.push(target);
        html.push('" ');
      }
      html.push('href="');
      html.push(url);
      html.push('">');
      addText(text);
      html.push('</a>');
    }
  };
}]);
                        I wanted a pause button that swaps text. here is how I did it:
in CSS:
.playpause.paused .pause, .playpause .play { display:none; }
.playpause.paused .play { display:inline; }
in template:
<button class="playpause" ng-class="{paused:paused}" ng-click="paused = !paused">
  <span class="play">play</span><span class="pause">pause</span>
</button>
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With