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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.