11

I'm trying to bind transcluded content to a variable inside of a component loop but I'm unable to do so.

I've looked at the PrimeNG's dropdowncomponent and they use the template tag along with let-car to bind to the car variable of the loop.

However when I try this I can't even get the content to transclude. What is the correct way of achieving this?

Attempts:

<!-- Obviously not gonna work -->
<comp>
  <span>{{option.name}}, {{option.type}}</span>
</comp>

<!-- Thought this would work but it doesn't, in odd scenarios I get the last element of the loop to transclude content and bind correctly. -->
<comp>
  <template let-option>
    <span>{{option.name}}, {{option.type}}</span>
  </template>
</comp>

In component:

<ul>
  <li *ngFor="let option of options">
    <ng-content></ng-content>
  </li>
</ul>

Simple plunkr of what I'm trying to achieve:

https://plnkr.co/edit/6SS03fuXmbvJB4nmf1AO?p=preview

Chrillewoodz
  • 27,055
  • 21
  • 92
  • 175

1 Answers1

16

Update Angular 6

ngOutletContext was renamed to ngTemplateOutletContext template should be ng-template

See also https://github.com/angular/angular/blob/master/CHANGELOG.md#500-beta5-2017-08-29

Original

You can get the template reference and add it using for example ngTemplateOutlet or ngForTemplate to get the template content added to the DOM. With ngTemplateOutlet you can provide your own context that you then can access with template variables as you tried.

class CompComponent {
  context = {option: 'some option'};
  constructor(private templateRef:TemplateRef){}
}
<ng-template [ngTemplateOutlet]="templateRef" [ngOutletContext]="{$implicit: context}"></ng-template>

I think in newer versions this needs to be

<ng-template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{$implicit: context}"></ng-template>

(but haven't yet verified)

See also

Marek
  • 3,935
  • 10
  • 46
  • 70
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • What exactly is `context` supposed to be? – Chrillewoodz Dec 20 '16 at 10:23
  • 1
    Might be something like "this" for that templateRef. I'm just guessing (: I'm looking into this pattern myself. – Sasxa Dec 20 '16 at 10:25
  • @GünterZöchbauer Can you explain in more detail how templateRef (and `let-something` attribute) work, if you have time? Docs are terrible (; – Sasxa Dec 20 '16 at 10:27
  • Also get `No provider for TemplateRef`, nvm I'm stupid. – Chrillewoodz Dec 20 '16 at 10:28
  • As far as I remember from when I last tried, `[ngOutletContext]="context"` is what is made available as context to the template. With ` – Günter Zöchbauer Dec 20 '16 at 10:31
  • `$implicit` is implicitly available and holds the whole `context` (just from the top of my head). I have to check, I'm sure I have posted some answer where this is actually used. – Günter Zöchbauer Dec 20 '16 at 10:33
  • Ok, but why am I getting `No provider for TemplateRef` though? I don't get it, I've injected it into the component.. – Chrillewoodz Dec 20 '16 at 10:37
  • Hard to tell what you're exactly doing from the few fragments. A Plunker would be really helpful. – Günter Zöchbauer Dec 20 '16 at 10:39
  • This is working https://plnkr.co/edit/oxO1ouwc2xzTN0R7pMgD?p=preview I don't know why injecting doesn't work and I have yet to figure out how `$implicit` can be used. – Günter Zöchbauer Dec 20 '16 at 11:05
  • Ok, I guess I'll go with what's working for now. Let me know if you manage to figure the other things out. – Chrillewoodz Dec 20 '16 at 11:11
  • `$implicit` isn't necessary but it might property access of the context easier. I'll add a comment when I know more. – Günter Zöchbauer Dec 20 '16 at 11:15
  • 1
    https://plnkr.co/edit/JuwbvVe5sBGMI9Xm2DsS?p=preview If the object passed to `ngOutletContext` has an `$implicit` property this can be made available by just `let-xxx` and then `xxx` gets the value of the `$implicit` property. – Günter Zöchbauer Dec 20 '16 at 11:20
  • Doesn't appear to know what `option` is though if you do this https://plnkr.co/edit/OlFCMASbWGCo7jwhEc3N?p=preview – Chrillewoodz Dec 20 '16 at 11:25
  • Sorry, can't figure out what you try to accomplish exactly. The template (A) is the one passed to `comp` in `my-app` and acquired by `@ContentChild(TemplateRef)`. The template (B) in comp (inside `*ngFor` is just to execute `ngTemplateOutlet` that renders template A for every `option of options`. `[ngOutletContext]` then passes data to A https://plnkr.co/edit/v086bAXiBe9Qd2qTvTka?p=preview – Günter Zöchbauer Dec 20 '16 at 11:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/131041/discussion-between-chrillewoodz-and-gunter-zochbauer). – Chrillewoodz Dec 20 '16 at 11:42
  • React is so much better aye – xaunlopez Jun 28 '19 at 07:34
  • 1
    Not sure how, but your response has helped me after hours of struggle, much appreciated! – kaffeemeister May 21 '20 at 09:25