Have you tried ngFor
in Angular 2? I bet you have. If you try the Angular 2 release candidate or later, you may have noticed a pervasive change that affects nearly every early adopter of Angular 2. The syntax changed very subtly.
The new syntax is super easy to refactor. However being inquisitive like we are, my friend Ward Bell and I wondered why it was made. This post helps explain why the late change happened based on our perceptions.
Most of this post came directly from my friend Ward's thoughts. I suggested it was awesome and useful information and requested he let me post it. He agreed. And here we are :)
Overview of *ngFor and ref-
Here are the changes to the micro-syntax for ngFor
.
- We now use
let item of items
instead of#item of items
inside*ngFor
. - Outside of
*ngFor
, replace allvar-x
withref-x
The terminology also subtly changed. What we used to call a local template variable is now either a template input variable (inside *ngFor
) or a template reference variable (outside *ngFor
).
The new *ngFor micro-syntax
Before beta.17 we wrote:
<div *ngFor="#hero of heroes; #i=index">
{{i + 1}} - {{hero.fullName}}
</div>
After beta.17, and including the RC's, we write:
<div *ngFor="let hero of heroes; let i=index">
{{i + 1}} - {{hero.fullName}}
</div>
The migration path is as simple as replacing #xxx
with let xxx
.
The old way will continue to work for a while longer. But it has been deprecated as you can see in a console warning message such as this:
"#" inside of expressions is deprecated. Use "let" instead! ("
<div [ERROR ->]*ngFor="#hero of heroes">{{hero}}</div>
"): StructuralDirectivesComponent@7:5
Why the change?
Outside of *ngFor
, a variable preceded by #
defines a template reference variable, typically a reference to an element in the DOM.
<input #heroBox >
<p>{{heroBox.value}}</p>
The heroBox
variable is a reference to the input box and we can use it to display its value property.
That's not what the hero
variable does inside the *ngFor
.
<div *ngFor="let hero of heroes; let i=index">{{i + 1}} - {{hero.fullName}}</div>
That hero
variable is not a reference to the <div>
!
It is actually an input to the (invisible) Angular function that repeats the <div>
template
for as many times as there are heroes in the list.
It's a different kind of variable, what we now call a template input variable.
We can't and shouldn't use the same syntax for both a template input variable and a template reference variable.
Thus the change was made.
let x
means that x
is a template input variable in an *ngFor
.
#x
means that x
is a template reference variable that usually references a DOM element; it cannot be used within an *ngFor
.
Use ref-, not var-
Before beta.17 we could write #x
as var-x
; this was an alternative syntax for those relatively few developers who prefer a prefix to the (#) symbol.
The var-x
syntax is now illegal. Starting in beta.17, we must write it as ref-x
in keeping with the new, clearer term: template reference variable.