159

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?

6
  • There is no such thing as dynamic reference variables. Why do you think it needs to be dynamic? Commented Jun 8, 2017 at 16:21
  • because their tutorial said in order to have html binding inside a popover, then we need to create a ng-template and refer it with template reference variable, but now I want to use this popover inside a ngFor element Commented Jun 8, 2017 at 16:25
  • 13
    Just do the same. The template variable will be different for each element even when it has the same name. Commented Jun 8, 2017 at 16:28
  • 4
    What happens if you use the same ref for everything? Have you tested it? Commented Jun 8, 2017 at 16:29
  • 1
    Yeah, it works... I tested it out... thanks for your solution Commented Aug 13, 2017 at 10:15

3 Answers 3

170

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

Plunker Example

For more details see also:

Sign up to request clarification or add additional context in comments.

1 Comment

Note that if you are using an @ViewChild, you cannot use this solution (and then should use @AlexBoisselle's one)
41

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!

1 Comment

Thanks, this solved a problem I had with ng-bootstrap nav-tabs that were created in a ngFor. Having the same reference, tabs were changing simultaneously.
2

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>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.