简体   繁体   中英

How to use directive for external link in angular?

I have a angular 8 application. And there is a possibility to enter a link.

But you have two kind of links:

internal and external. with external I mean outside the domain of the site. For example: http://www.ad.nl

Then if a user click on that link the user has to be redirected to other tab with that link.

But you can also have a internal link: like this: http://localhost:4200/gezondheid/Measurement/actieindex

But then the link has to be opening in the same tab.

I have a directive for it like this:

@Directive({
  selector: '[appExternalLink]'
})

/**
 * This directive is responsible for checking if in Activity the link is a external link - then it wil open
 * in a seperate tab or is the link an internal(same domain) link, then it will open in the same tab
 */
export class ExternalLinkDirective {

  @HostBinding('attr.rel') relAttr = '';
  @HostBinding('attr.target') targetAttr = '';
  @HostBinding('attr.href') hrefAttr = '';
  @Input() href: string;

  /**
   * Check if liink is external or not
   */
  ngOnChanges() {
    this.hrefAttr = this.href;

    if (this.isLinkExternal()) {
      this.relAttr = 'noopener';
      this.targetAttr = '_blank';
    }
  }

  /**
   * if link is external, then set the rel and target attributes
   */
  private isLinkExternal() {
    return !this.href.includes(location.hostname);
  }

and I inject it in the component like this:

 <a appExternalLink
      *ngIf="activity.link; else nolink"
      [href]="activity.link">
      <div class="todo-day-part-subject">{{ activity.subject }}</div>
      <div class="todo-day-part-block">
        <div class="todo-day-part-icon {{ getIcon(activity.type) }}"></div>
        <div class="todo-day-part-content">
          <div class="todo-day-part-text">{{ activity.text }}</div>
          <div class="todo-day-part-time">{{ activity.beginDate | date: 'HH:mm' }}</div>
          <div *ngIf="activity.link" class="todo-day-part-readmore">Bekijk</div>
          <div *ngIf="activity.state === 'Done'" class="todo-day-part-status-signal">
            <span class="fa fa-check-circle"></span>
          </div>
        </div>
      </div>
    </a>

But it works for now fo intern link. But if the link is: http://www.ad.nl then it will open in the same tab en not in a seperate tab.

So what I have to change?

Thank you

Well first off, with internal link, I guess you do not mean a link that's inside the angular app, because for that you have to use [routerLink] . If it's just to a different page outside of the angular app but inside the same domain, I believe you should do the following:

@Directive({
  selector: 'a[appExternalLink]'
})
export class ExternalLinkDirective {

  @HostBinding('rel')
  rel = '';

  @HostBinding('target')
  target = '_self';

  @Input()
  @HostBinding('href')
  href?: string;

  ngOnChanges(changes: SimpleChanges) {
    if (changes.href) {
      const isExternal = this.isLinkExternal();
      this.rel = isExternal ? 'noopener' : '';
      this.target = isExternal ? '_blank' : '_self';
    }
  }

  /**
   * Check if link is external or not
   */
  private isLinkExternal() {
    return !(this.href || '').includes(location.hostname);
  }
}

This basically means, don't use the attr. binding, because that doesn't work in this case :) You need to update the property, not just the attribute.

stackblitz

I've created a simple example of how else you could solve this task

The idea is to prevent default behavior of link tags and resolve routing via javascript.

Also, you dont need to know about link type on every ngOnChanges fire. So you can check it only on click event and make decision where to route your customer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM