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