angularangular2-ngcontent

Angular doesn't render second <ng-content></ng-content>


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

}

Solution

  • 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>