1

I'm trying to watch the content of ng-html-bind and modify the div content to auto link all hyperlinks in the div since the original content will not have hyperlink html.

Here is the plunker

Here is the directive

app.directive('autolink', ['$compile', '$timeout', function ($compile, $timeout) { return { restrict: 'EA', replace: true, link: function (scope, element, attrs) { $timeout(function () { var text = element[0].innerHTML; var linkTypes = ["http://", "https://"]; linkTypes.forEach(function (linkType) { var startSpace = 0; while (startSpace >= 0) { text = element[0].innerHTML; var locationOfHttp = text.indexOf(linkType, startSpace); if (locationOfHttp < 0) break; var locationOfSpace = text.indexOf(" ", locationOfHttp); var textAfter = ""; if (locationOfSpace < 0) { locationOfSpace = text.length; } else { textAfter = text.substring(locationOfSpace, text.length); } var linkUrl = text.substring(locationOfHttp, locationOfSpace); var htmlText = text.substring(0, locationOfHttp) + '<a href="' + linkUrl + '">' + linkUrl + '</a>' + textAfter; element[0].innerHTML = htmlText; startSpace = (text.substring(0, locationOfHttp) + '<a href="' + linkUrl + '">' + linkUrl + '</a>').length - 1; } }); scope.$apply(); console.log("autolink"); }, 1); }, }; }]); 

My directive is working when the page loads but not when I click on the change URL, div is not auto linking. How do I watch for the change and run the directive on change ?

6
  • 1
    Why wouldn't you do this in controller or service before sending html to the view? Or create a filter for it Commented Jun 1, 2016 at 21:29
  • @charlietfl: Yes, I could do that. Will do that until someone answers here. Since this is a display thing, thinking directive will be a good way of doing this. Commented Jun 1, 2016 at 21:31
  • Doesn't make sense to me...if you know it needs to be modified, why wait until it's in the DOM to modify it? Commented Jun 1, 2016 at 21:33
  • Haha, @charlietfl, that is so much more efficient then my answer. Commented Jun 1, 2016 at 21:39
  • @cm92 wouldn't you agree no need for directive at all? Seems like overkill for something that can be done so simply in advance Commented Jun 1, 2016 at 21:42

1 Answer 1

1

So you can use scope.$watch() to watch for the change on a scope variable, run it through your link creating function, and then add it back in to the element.

Here is a fork of your plunk that does just that.

I changed ng-bind-html to be autolink by way of using an isolate scope (Directive isolate scope), which allows your new text with the urls in it to be passed to the directive, where the scope.$watch takes over. By making the isolate scope variable the same as the directive name, you can use it both to invoke the directive and pass a variable into it.

The new html:

<div autolink="parseResult(details)"></div> 

Here is the code for the directive below:

app.directive('autolink', ['$compile', '$timeout', function ($compile, $timeout) { return { restrict: 'EA', replace: false, // isolate scope below the html attribute // unlinked-text is automatically translated // to the scope variable unlinkedText by angular. scope: { autolink: '=' }, // added a template that uses ng-bind-html with // your new, link-ified text template: '<span ng-bind-html="text"></span>', link: function (scope, element, attrs) { scope.text = scope.autolink; function addLinks(str) { var text = str; console.log(text.match(/https?:\/\/\w*/)); var links_parsed = text .replace(/https?:\/\/[\w\.\/]*/g, function(substr) { return '<a href="' + substr + '">' + substr + '</a>'; }); return links_parsed; } // Still using timeout for initial run of addLinks $timeout(function() { scope.text = addLinks(scope.text); },0) // scope watches autolink variable scope.$watch('autolink', function(newVal, oldVal) { if(newVal !== oldVal) { // if variable has changed... scope.text = addLinks(newVal); // ...runs addLinks() again } } ); } }; }]); 
Sign up to request clarification or add additional context in comments.

5 Comments

Can we pass the text to autolink attribute instead of unlinked-text ?
@TechCrunch I updated the answer. It now uses the same attribute name as an isolate scope variable. So you can pass in your new text directly on autolink="", I updated the plunkr as well, if you want to see it in action.
@cm02 thanks much. As per charlietfl's suggestion, for now I'm going to call addLinks directly in controller. But this example is definitely going to be helpful to me in future and someone else.
@cm02, your addLinks function does not include abc for hyperlink in google.com/abc
@TechCrunch Yeah, the regex wasn't catching anything after a /, should be fixed now, changed /https?:\/\/[\w\.]*/g to /https?:\/\/[\w\.\/]*/g.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.