首页 > 解决方案 > 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

标签: javascriptangulartypescript

解决方案


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


推荐阅读