Reputation: 11060
How do I pass the current variable in an ngFor loop to ngIf, if it is using templates with then/else syntax?
It appears that they pass through fine when used inline, but aren't accessible from a template, for example:
<ul *ngFor="let number of numbers">
<ng-container *ngIf="number % 2 == 0; then even_tpl; else odd_tpl"><>/ng-container>
</ul>
<ng-template #odd_tpl>
<li>Odd: {{number}}</li>
</ng-template>
<ng-template #even_tpl>
<li>Even: {{number}}</li>
</ng-template>
The templates don't seem to have access to number
at all, but it works if used inline.
A full example of the working and not-working versions in the following link: plunkr
Upvotes: 35
Views: 16822
Reputation: 4460
All answers use the same name for key-value, So at the first look, it makes me confuse.
Here working example for Angular 10
<div *ngFor="let data of dataList">
<ng-container *ngTemplateOutlet="data.istruevalue ? truevalue : falsevalue ; context: { passdata:data}"></ng-container>
</div>
<ng-template #truevalue let-info="passdata">
<label >true : {{info.name}}</label><br>
</ng-template>
<ng-template #falsevalue let-info="passdata">
<label >false : {{info.name}}</label><br>
</ng-template>
Upvotes: 0
Reputation: 1810
Here are couple more (similar) options for multiple arguments, this one includes using 'ngTemplateOutletContext' and also a condition (in 4th argument - for fun).
... should work by copy and paste ...
<!-- DEMO using:
"=templateID; context:{prop:value, ...}"
( 4 arguments demo)
Note: $implicit identifies the default argument in the template.
The template does not need to assign the argument name,
- see the 3rd argument
-->
<div *ngFor="let item of ['Aaa', 'Bbb', 'Ccc']; index as ix">
<ng-container *ngTemplateOutlet="myTemplate1;
context:{cDemoName:'Option 1:',
cIx:ix+1,
$implicit:item,
cIsEven: ((ix % 2) === 0) ? 'true' : 'false' }">
</ng-container>
</div>
<hr>
<!-- DEMO using:
[ngTemplateOutlet]="templateID"
[ngTemplateOutletContext]="{"=templateID; context:{prop:value, ...}"
-->
<div *ngFor="let item of ['Dddd', 'Eee', 'Fff']; index as ix">
<ng-container [ngTemplateOutlet]="myTemplate1"
[ngTemplateOutletContext]="{
cDemoName:'Option 2',
cIx:ix+1,
$implicit:item,
cIsEven: ((ix % 2) === 0) ? 'true' : 'false' }
">
</ng-container>
</div>
<!-- DEMO template:
( 4 arguments expected)
-->
<ng-template #myTemplate1
let-cDemoName="cDemoName"
let-cIx="cIx"
let-cItem
let-cIsEven="cIsEven">
Context arguments demo name: {{cDemoName}} <br>
. . . . . Context index: {{cIx}} <br>
. . . . . Context item: --- {{ cItem }} --- <br>
. . . . . Context is-even: {{ cIsEven }} <br>
<br>
</ng-template>
Upvotes: 0
Reputation: 980
look here: Pass variable in Angular 2 template
<div *ngFor="foo in foos">
<ng-container *ngTemplateOutlet="inner; context:{name:foo}"></ng-container>
</div>
<ng-template #inner let-name="name">
{{ name }}
</ng-template>
Upvotes: 7
Reputation: 1467
It's because the way template scope works. Templates in Angular have dynamic scope instead of regular javascript lexical scope, that means, the {{ number }}
expression inside the ng-template
is not pointing to the same number
variable in your *ngFor
, although one should think it would since you're kinda evaluating the template expression where <ng-container>
is.
If you actually define a number
property in your AppComponent
, let's say number = 42
, you can see that all the {{number}}
expressions inside <ng-template>
evaluates to 42
.
So either you should define your templates inside the scope of the *ngFor
, where the number
variable has the desired value, or somehow pass this value to both even_tpl
and odd_tpl
. As @Vivek has pointed out, you can do this with ngTemplateOutlet
and ngTemplateOutletContext
.
Upvotes: 1
Reputation: 58523
All you need is to use [ngTemplateOutletContext]
Read More
Here is the way how you can achieve that :
<div>
<h3>All Templates</h3>
<ul *ngFor="let number of numbers">
<ng-container [ngTemplateOutlet]='number % 2 == 0 ? even_tpl : odd_tpl' [ngTemplateOutletContext]="{number:number}"></ng-container>
</ul>
</div>
<ng-template #odd_tpl let-number='number'>
<li>Odd: {{number}}</li>
</ng-template>
<ng-template #even_tpl let-number='number'>
<li>Even: {{number}}</li>
</ng-template>
Upvotes: 41