Introduction
<div *ngFor="let leaf of ['π', 'ππ', 'πππ']; let i = index;">
<p>{{i + 1}}. {{leaf}}</p>
</div>
1. π
2. ππ
3. πππ
If you've worked with Angular, I'm sure you've come across this *ngFor syntax at least once: let leaf of ['π', 'ππ', 'πππ']; let i = index;". However, have you ever wondered?
- Is there any alternative
*ngForsyntax? - Where does the
indexvariable come from? - How does the
leafvariable iterate over and reference items of['π', 'ππ', 'πππ']? - Why is it
let ... of ...? Can we change it tolet ... something ...?
What do you think about trying the following syntaxes with
*ngFor?
1. let leaf of ['π±', 'π', 'πΏ']; let i = index;
2. let leaf; let i = index; of ['π±', 'π', 'πΏ'];
3. let i = index; let leaf; of ['π±', 'π', 'πΏ'];
4. let i = index let leaf; of: ['π±', 'π', 'πΏ'];
5. let i = index; of ['π±', 'π', 'πΏ']; let leaf;
6. let i = index; of: ['π±', 'π', 'πΏ'] let leaf;
7. 'Magic πͺ'; let i = index; of: ['π±', 'π', 'πΏ']; let leaf;
8. let leaf = $implicit of ['π±', 'π', 'πΏ']; let i = index;
9. let leaf = $implicit; let i = index; of ['π±', 'π', 'πΏ'];
10. let leaf = $implicit, let i = index, of ['π±', 'π', 'πΏ'];
You can quickly find the answer via this StackBlitz link.
Surprisingly, these peculiar syntaxes compile without any errors. π€
How does this happen? What are the rules behind these syntax variations?
Demystifying *ngFor syntax
At first glance, you might be under the impression that you're required to use a semicolon to delimit the calls and adhere to a certain order, or that there might be more rules you don't yet understand about how to use the syntax. But that's not the case - the syntax is actually quite flexible more than that.
Angular's microsyntax has 4 building blocks, that when combined in a particular way, make up the entire microsyntax API. These building blocks are:
- Expressions
- The
askeyword - Keyed expressions
-
letbindings
1. Expressions
Anything that, when referenced, returns a value.
- Raw value
<p *hello="'π Hey there'"></p>
- Calling a function
<p *hello="greeting()"></p>
- Referenced a variable
<p *ngIf="shouldDisplay"></p>
- Operator (
9 * 9)
2. The
askeyword
The rules behind the as keyword as an alternative to let. The most commonly used is combining between *ngIf and AsyncPipe.
<div *ngIf="(myFutureGirl$ | async) as myFutureGirl">
{{myFutureGirl}}
<div>
Oops, 404 π€¦ββοΈ
3.
keyExp- Key Expressions
A key expression is simply an expression that you're able to bind to an input on a structural directive.
For example, the *ngFor directive includes an ngForOf input as follows:
/**
* The value of the iterable expression, which can be used as a
* [template input variable](guide/structural-directives#shorthand).
*/
@Input()
set ngForOf(ngForOf: U&NgIterable<T>|undefined|null) {
this._ngForOf = ngForOf;
this._ngForOfDirty = true;
}
In this case, the key expression is the of keyword. This directly answers the question, Why is it let ... of ...?
4.
letbindings
The let binding is used for reference the Template Context. Let's take a look at our example:
let leaf of ['π±', 'π', 'πΏ']; let i = index;
There are two types of references made using let bindings:
- Implicit
In this case, the assigned expression on the right side is omitted, and it is equivalent to the following:
let leaf = $implicit
Angular automatically assigns the reference with the $implicit key in the context.
- Explicit
let i = index
When we use let i = index, it is clear that the variable i references the index key in the context.
Combining Things Together
- It starts with the * reserved token. It is an Angular special syntax companion with the Angular Structural Directive.
- Then, you have to declare the
selectorvalue of the directive itself. - Finally, you can bind to the
selectoras with any other input using the=token.
The contents of the input itself are where the microsyntax goes.
1. First Item
Either an expression or a let binding.
If an expression is passed, the value of the expression will be passed to the same input name as the selector itself.
Let's take a look at *ngIf implementation:
@Directive({
selector: '[ngIf]',
standalone: true,
})
export class NgIf<T = unknown> {
/**
* The Boolean expression to evaluate as the condition for showing a template.
*/
@Input()
set ngIf(condition: T) {
this._context.$implicit = this._context.ngIf = condition;
this._updateView();
}
}
*ngIf includes an ngIf input that is the same as the [ngIf] selector itself.
If a let binding is the first item, it will work exactly as it's explained in the previous section.
<!-- β
These ARE valid for the first item -->
<p *ngIf="'Expression'"></p>
<p *ngFor="let i = index; ..."></p>
<!-- π But these are NOT valid for the first item -->
<p *ngFor="of: ['π±', 'π', 'πΏ']; ..."></p>
<p *ngFor="index as i"></p>
2. Second Item and Beyond
After the first item, youβre able to pass in a let binding, an as binding, or a key expression.
Let's revisit these *ngFor syntaxes at the very beginning of this post:
1. let leaf of ['π±', 'π', 'πΏ']; let i = index;
2. let leaf; let i = index; of ['π±', 'π', 'πΏ'];
3. let i = index; let leaf; of ['π±', 'π', 'πΏ'];
4. let i = index let leaf; of: ['π±', 'π', 'πΏ'];
5. let i = index; of ['π±', 'π', 'πΏ']; let leaf;
6. let i = index; of: ['π±', 'π', 'πΏ'] let leaf;
7. 'Magic πͺ'; let i = index; of: ['π±', 'π', 'πΏ']; let leaf;
8. let leaf = $implicit of ['π±', 'π', 'πΏ']; let i = index;
9. let leaf = $implicit; let i = index; of ['π±', 'π', 'πΏ'];
10. let leaf = $implicit, let i = index, of ['π±', 'π', 'πΏ'];
In fact, these *ngFor syntaxes end up with the same result:
<ng-template ngFor let-leaf [ngForOf]="['π±', 'π', 'πΏ']" let-i="index">
...
</ng-template>
Optional Separators
One side note, maybe you've already figured out from these *ngFor syntaxes above.
Just as the : is optional in the a key expression, all separators in the micro syntax are optional.
π Hey there
If you want to gain more insights into how Angular Structural Directives internals, you can reference my previous blog post Demystifying the Angular Structural Directives in a nutshell
Thank you for making it to the end
Thank you for choosing to read this blog post among the tens of thousands of great blog posts out there. And I will be really happy if you find something interesting from my blog post.
Reference


Top comments (0)