How can I conditionally use either [href] or [routerLink] on an anchor?

旧时模样 提交于 2019-12-04 23:25:39
developer033

The simplest way would be to use *ngIf / else:

<ng-container *ngIf="outside; else internalBlock">
  <a [href]="externalUrl">External</a>
</ng-container>

<ng-template #internalBlock>
  <a [routerLink]="['/route', id]">Internal</a>
</ng-template>

EDIT#1: (Ugly workaround)

Since you don't want to use *ngIf (I still don't understand why), you can do this:

Template:

<a href="javascript:void(0)" (click)="handleClick(outside, '/route', id, externalUrl)">Link</a>

Component:

handleClick(outside: boolean, internalUrl: string, internalId: string, externalUrl: string): void {
  if (outside) {
    window.location.href = externalUrl;
    // You can also use Location class of Angular
  } else {
    this.router.navigate([`${internalUrl}/${internalId}`]);
  }
}
ohjeeez

For a conditional href, prepending on attr. before the href worked for me using null as a value, like this:

[attr.href]="!item.subMenu ? item.url : null"
Tito Leiva

After a lot of investigation, I implemented a different approach to this issue, since my <a href>...</a>contains code inside (a clickable div for example). For instance, I don't want to use ngIf because that forces me to duplicate the div's inside code. So this is my solution:

Component HTML

<div>
   <a [href]="getRouterLink()" >
     <div class="section">
     <!-- stuff inside the div -->
     </div>   
   </a>
</div>

Component JS

Component({
selector: 'app-home-section',
templateUrl: './home-section.component.html',
styleUrls: ['./home-section.component.scss']
})
export class HomeSectionComponent implements OnInit {

@Input() link: string;

constructor(private router: Router) { }

ngOnInit() {
}

isRouterLink() {

  if (this.link) {
    let firstLinkChar = this.link.charAt(0);
    let isSlash = firstLinkChar == '/';
    return isSlash;
  }

  return false;
}

getRouterLink() {

  let url = this.isRouterLink() ? window.location.origin + this.link : 'http://' + this.link;  
return url;
 }
}

This was the only way to make it work simplier, because even I put the "www.example.com" directly to the href (with or without the [ ]), it always append the base url. It's not pretty, but is functional.

taras-d

You can access routerLink instance by injecting RouterLinkWithHref in the directive.

Directive:

import { ElementRef, Optional, Input, Directive, OnChanges } from '@angular/core';
import { RouterLinkWithHref } from '@angular/router';

@Directive({
  selector: '[externalLink]'
})
export class ExternalLinkDirective implements OnChanges {

  @Input() externalLink: string;

  constructor(
    private el: ElementRef,
    @Optional() private link: RouterLinkWithHref
  ) {}

  ngOnChanges(){

    if (!this.link || !this.externalLink) {
      return;
    }
    this.el.nativeElement.href=this.link.href=this.externalLink;

    // Replace onClick
    this.link.onClick = (...args: any[]) => {
      return true;
    }

  }

}

Usage:

<!-- Ignore router link and use external link -->
<a routerLink="/some/path" externalLink="https://google.com">Link</a>

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!