The new Control Flow syntax for Angular has been introduced with Angular 17 release, as a developer preview.
It replaces *ngIf
, *ngFor
, and *ngSwitch
with a new syntax that is more expressive and easier to read.
@for(article of articles$ | async; track article.id) {
<article>
<h2>{{ article.title }}</h2>
<p>{{ article.content }}</p>
</article>
}
The Angular team added a new feature to enhance the @for block: the @empty block.
The content of this block will be displayed if the list is empty or undefined.
@for(article of articles$ | async; track article.id) {
<article>
<h2>{{ article.title }}</h2>
<p>{{ article.content }}</p>
</article>
} @empty {
<p>No articles found</p>
}
The problem
A common misconception is to think that the @empty block is evaluated only once the data is retrieved from an asynchronous call.
In most usecases, you iterate over a list of items retrieved from an API.
As the API call is asynchronous, the list is undefined/empty at the component initialization.
From our point of view:
- The list is evaluated as empty
- The data is retrieved from the API
- The list is evaluated once again and display the empty block if the list is empty
From an end user point of view:
- The empty block is displayed at the beginning
- The view is updated with the list of items once the data is retrieved if a non-empty list is returned
It means we are displaying the empty block at the wrong time!
For a second (or more depending on your API response time), the user sees the empty block before the list is displayed.
They might think that the list is really empty, while it's not.
The solution
You need to wrap your existing logic to deal with the loading state of the list.
@if(articles$ | async as articles) {
@for(article of articles; track article.id) {
<article>
<h2>{{ article.title }}</h2>
<p>{{ article.content }}</p>
</article>
} @empty {
<p>No articles found</p>
}
} @else {
<p>Loading...</p>
}
There, instead of displaying the @empty block while you are waiting for the list to be retrieved, you display a loading message.
The @empty block will be evaluated once the list is retrieved and displayed at the right time.
Top comments (1)
Hi Gérôme Grignon,
Top, very nice and helpful !
Thanks for sharing.