I am trying to build a 'SmartLinkComponent' that can distinguish between internal and external links and at the same time, can wrap any html content in tag. I came up with the following solution (smart-link.component.html):
<a *ngIf="!isInternal" [href]="link" target="_blank" [title]="title">
<ng-content></ng-content>
</a>
<a *ngIf="isInternal" [routerLink]="link" [title]="title">
<ng-content></ng-content>
</a>
The logic for resolving isInternal
variable works flawlessly so I am not including the code here.
The problem is that this code only works for the first that occurs in the layout. Code posted above only renders links that are !isInternal
. When I swap the code like this:
<a *ngIf="isInternal" [routerLink]="link" [title]="title">
<ng-content></ng-content>
</a>
<a *ngIf="!isInternal" [href]="link" target="_blank" [title]="title">
<ng-content></ng-content>
</a>
then angular only renders <ng-content></ng-content>
for internal links.
It even seems like <ng-content></ng-content>
can be used only once in the layout when it doesn't have any associated select
directive with it but I couldn't find any documentation regarding this. However, the *ngIf
conditions here are mutually exclusive, so I am really not sure what's the issue.
Edit: here's (anonymized) code for smart-link.component.ts:
import {Component, Input, OnInit} from '@angular/core';
@Component({
selector: 'app-smart-link',
templateUrl: './smart-link.component.html',
styleUrls: ['./smart-link.component.scss']
})
export class SmartLinkComponent implements OnInit {
isInternal: boolean = true;
@Input("href") originalLink: string;
@Input() title: string;
link: string;
constructor() {
}
ngOnInit() {
if (this.originalLink) {
console.log('original link', this.originalLink);
if (some rules) {
this.isInternal = true;
this.link = // transform link
} else {
this.isInternal = false;
this.link = this.originalLink;
}
}
console.log('evaluating link', this.originalLink, ' as internal ', this.isInternal, this.link);
}
}
As @Shikha mentioned in the comment, it's not possible to use several ng-content elements without specifying the 'select' directive. Using this response from angular GitHub repository https://github.com/angular/angular/issues/24567 I was able to fix the solution to only include ng-container once as follows:
<a *ngIf="link && !isInternal" [href]="link" target="_blank" [title]="title">
<ng-container *ngTemplateOutlet="linkTemplate"></ng-container>
</a>
<a *ngIf="link && isInternal" [routerLink]="link" [title]="title">
<ng-container *ngTemplateOutlet="linkTemplate"></ng-container>
</a>
<ng-template #linkTemplate>
<ng-content></ng-content>
</ng-template>