0

There is a similar question out there, but it only applies to hard-coded hrefs, not ones that are interpolated by angular. See Conditionally add target="_blank" to links with Angular JS

The solution I'm looking for is best illustrated by the following directive:

yourModule.directive('a', function() {
  return {
    restrict: 'E',
    link: function(scope, elem, attrs) {
      var a = elem[0];
      if (location.host.indexOf(a.hostname) !== 0)
        a.target = '_blank';
    }
  }
}

The problem is that the directive runs before angular has done any interpolation, and therefore all links appear relative. Is there a clean way to do this? I can't use mutation observers, because I must support IE9.

Community
  • 1
  • 1
w.brian
  • 16,296
  • 14
  • 69
  • 118

2 Answers2

4

I would suggest to use 2 option that was already provided:

<a href="http://www.google.com" target="{{condition ? '_blank' : '_self'}}">Link</a>

and set condition variable in directive controller, depending on location.

If you provide sandbox for this issue it would be really helpful.

UPD: if you want to have more hacks you could you $timeout and wrap it there.

Stepan Suvorov
  • 25,118
  • 26
  • 108
  • 176
  • This would require adding markup to every link. I am looking for a solution that wouldn't require additional markup. – w.brian Nov 17 '14 at 14:43
  • I got your point. But it's normal to add attribute otherwise it would be attribute directive. ".directive('a'," - look's like hack for me – Stepan Suvorov Nov 17 '14 at 14:47
  • I disagree that .directive('a')... would be a hack. It does exactly what I want it to do -- change the behavior of all links to open external hrefs in a new tab. It's the opposite of a hack IMO. It's elegant and totally self-contained. – w.brian Nov 17 '14 at 14:51
  • I would say you extend element behaviour in non-declarative way. For me it's like extend/rewrite JS native object prototypes. – Stepan Suvorov Nov 17 '14 at 15:16
2

The solution ended up being quite simple. Angular provides a built-in way to observe attributes and react to changes:

yourModule.directive('a', function() {
  return {
    restrict: 'E',
    link: function(scope, elem, attrs) {
      attrs.observe('href', function(){
        var a = elem[0];
        if (location.host.indexOf(a.hostname) !== 0)
          a.target = '_blank';
      }
    }
  }
}
w.brian
  • 16,296
  • 14
  • 69
  • 118