Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opening Angular 6 links bound by [innerHTML] in a new tab

I have an Angular 6 app with a <div> that gets populated via an [innerHTML] binding. How can I apply target='_blank' to all the links inside this div?

What I've tried:

So far, I've tried creating a directive that wraps the div and, after change detection gets run, pulls up a list of child <a> tags and applies a target='_blank' attribute. So far, I have not been able to get ContentChildren to access any of the links: It just pulls up an empty list.

Does anyone have experience doing this, or is there a more elegant solution?

@Directive({
  selector: '[appExternalLink]'
})
export class ExternalLinkDirective implements AfterContentChecked, AfterViewChecked {

  @ContentChildren('a', {descendants: true}) links: QueryList<any>;


  @Input() appExternalLink: string;
  constructor() {
    console.log('HELLO FROM APPEXTERNALLINK');
  }

  ngAfterContentChecked() {
    console.log(this.links);
  }

}

Then, when binding the content:

<div appExternalLink>
  <div [innerHTML]="content"></div>
</div>
like image 922
caitlin Avatar asked Nov 05 '18 16:11

caitlin


2 Answers

It turns out I was using the wrong approach trying to use ContentChildren.

With the below code, I was able to target all <a> tags in a div with the appExternalLink directive. Posting my solution so other people don't have to figure this out themselves:

  import { AfterViewChecked, Directive, ElementRef } from '@angular/core';

  @Directive({
    selector: '[appExternalLink]'
  })
  export class ExternalLinkDirective implements AfterViewChecked {
    constructor(private el: ElementRef) { }

    ngAfterViewChecked() {
      Array.from(this.el.nativeElement.querySelectorAll('a'))
        .forEach((el: any) => {
          el.setAttribute('target', '_blank');
        });
    }
  }
like image 112
caitlin Avatar answered Sep 30 '22 13:09

caitlin


You can use the <base> tag to default the target attribute of each anchor.

<base target="_blank">

You can inject this tag dynamically in ngOnInit and remove it in ngOnDestroy, but it will change the behaviour of any link.

If you want to change the behaviour of just the anchors inside a div, you can use

Array.from(document.querySelectorAll('.your-div-class a'))
  .forEach(el => el.setAttribute('target', '_blank'))
like image 27
Cristian Traìna Avatar answered Sep 30 '22 13:09

Cristian Traìna