How can I conditionally use either [href] or [rout

2020-03-08 08:21发布

问题:

I need for the same anchor link to be pointed conditionally locally or to external resource. I tried

<a [href]="outside?externalUrl:null"  [routerLink]="outside?[]:['/route',id]" >test</a>

But it doesn't work. I don't get any errors, but it points to the same local page and ignores the external URL. Any ideas?

Another option would be to construct the link, but I can't find any docs how to access routerLink inside a service

Edit: I know I can clone the whole link with *ngIf but I don't want to do it, my link contains a video tag with a buch of options

回答1:

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}`]);
  }
}


回答2:

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"


回答3:

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.



回答4:

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>