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,
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
.
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>
WORKING DEMO
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 ['Dffffd', '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>
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>