I have a component with multiple ng-content
. Basically if you passed a routerLink
Input into the component, it will render <a>
tag, otherwise it will render <button>
tag. Obviously it is not how you design a link component but it is a good example. I actually did it around 2016 when I was learning Angular 😂
@Component({
selector: 'app-link',
template: `
<a *ngIf="routerLink" [routerLink]="routerLink">
{{ routerLink }} - <ng-content></ng-content>
</a>
<button *ngIf="!routerLink">
<ng-content></ng-content>
</button>
`,
styles: [],
})
export class LinkComponent {
@Input() routerLink: string
}
And you would probably notice that the <a>
tag was render but nothing come has been projected into <ng-content>
.
<app-link routerLink="active">My link</app-link>
<br />
<app-link>My button</app-link>
The result come, but only the My button
text get projected.
There are several issues has been created on the angular repository regarding this issue, for example #9173 and #22972.
Why it is working this way, I don’t think I can explain in an easy way for you. Therefore feel free to check misko’s detailed comment
One notable workaround can be found on #22972 nelisbijl’ comment. Essentially, you don’t try to render multiple ng-content, but putting ng-content
inside an ng-template
and render that template inside your ngIf
.
@Component({
selector: 'app-link-fixed',
template: `
<a *ngIf="routerLink" [routerLink]="routerLink">
{{ routerLink }} -
<ng-container *ngTemplateOutlet="contentTmpl"></ng-container>
</a>
<button *ngIf="!routerLink">
<ng-container *ngTemplateOutlet="contentTmpl"></ng-container>
</button>
<ng-template #contentTmpl>
<ng-content></ng-content>
</ng-template>
`,
styles: [
`
:host {
display: block;
}
`,
],
})
export class LinkFixedComponent {
@Input() routerLink: string
}