Dynamic template reference variable inside ngFor (Angular 9)
AngularNg BootstrapAngular TemplateAngular Problem Overview
How to declare a dynamic template reference variable inside a ngFor
element?
I want to use the popover component from ng-bootstrap, the popover code (with Html binding) is as shown:
<ng-template #popContent>Hello, <b>{{name}}</b>!</ng-template>
<button type="button" class="btn btn-secondary" [ngbPopover]="popContent" popoverTitle="Fancy content">
I've got markup and bindings in my popover!
</button>
How can I wrap those elements inside ngFor
?
<div *ngFor="let member of members">
<!-- how to declare the '????' -->
<ng-template #????>Hello, <b>{{member.name}}</b>!</ng-template>
<button type="button" class="btn btn-secondary" [ngbPopover]="????" popoverTitle="Fancy content">
I've got markup and bindings in my popover!
</button>
</div>
Hmmm... any idea?
Angular Solutions
Solution 1 - Angular
Template reference variables are scoped to the template they are defined in. A structural directive creates a nested template and, therefore, introduces a separate scope.
So you can just use one variable for your template reference
<div *ngFor="let member of members">
<ng-template #popupContent>Hello, <b>{{member.name}}</b>!</ng-template>
<button type="button" class="btn btn-secondary" [ngbPopover]="popupContent" popoverTitle="Fancy content">
I've got markup and bindings in my popover!
</button>
</div>
and it should work because it has already declared inside <ng-template ngFor
For more details see also:
Solution 2 - Angular
This is the best solution I've found: https://stackoverflow.com/a/40165639/3870815
In that answer they use:
@ViewChildren('popContent') components:QueryList<CustomComponent>;
To build a list of those dynamically generated components. Highly recommend you check it out!
Solution 3 - Angular
Another way to allow this is to create a component that wraps the button and the ng-template
<div *ngFor="let member of members">
<popover-button [member]="member"></pop-over-button>
</div>
And have the following in the popover-button component
<ng-template #popContent>Hello, <b>{{member.name}}</b>!</ng-template>
<button type="button" class="btn btn-secondary" [ngbPopover]="popContent" popoverTitle="Fancy content">
I've got markup and bindings in my popover!
</button>
Solution 4 - Angular
You can use trackBy: trackByFn
in *ngFor
<div *ngFor="let member of members;trackBy: trackByF">
<ng-template #popupContent>Hello, <b>{{member.name}}</b>!</ng-template>
<button type="button" class="btn btn-secondary" [ngbPopover]="popupContent" popoverTitle="Fancy content">
I've got markup and bindings in my popover!
</button>
</div>