Angular 17's New Control Flow Syntax Explored
Angular 17 shipped with a fresh control flow syntax, and it represents a significant shift from the previous approach. Alongside other features we'll examine in future posts, this new syntax marks a clear departure from how control flow has traditionally been written in Angular templates.
Control flow governs the sequence in which statements execute within a script. Conditional constructs (if…else, switch) determine which statements run or are skipped based on conditions, while loops enable repeated execution.
Subscribed
Angular now offers a new control flow syntax, a substantial change from the former style (referred to here as the old syntax), which remains in use since the new syntax is still in developer preview.
Let's begin by contrasting the new syntax against the old one.
Conditional Rendering with If
Suppose we need to display a template section only when conditions are met. Under the old syntax, the approach was:
Old if….else conditional syntax in Angular
With the new syntax, the same logic is expressed as:
New Angular if…else conditional syntax
This can be further condensed to:
Iterating with For Loops
Consider for loops:
Old
For Loop before V17
New
New Angular For Loop Syntax
Notice that we supply a tracking expression, which produces a unique key to bind each array item to its corresponding DOM position for performance optimization. This is mandatory in the new syntax, whereas it was optional previously.
Switch Statements with NgSwitch
Here's the old way:
And this is how it looks with the new syntax:
Did you spot the difference? The new syntax is more readable (admittedly subjective, but likely agreeable) and feels familiar—it mirrors the syntax you'd encounter when writing TypeScript, JavaScript, or most other languages. For newcomers, deciphering the old syntax often required a few puzzled looks and squinted eyes.
Another major advantage is syntax highlighting and formatting. With the old syntax, highlighting was limited because structural directives lived within HTML attributes. Now that control flow is separate from HTML tags, highlighting works out of the box. Additionally, the prettier npm package (ensure you're on the latest version) supports formatting for the new Angular syntax, which is quite impressive.
Combined, these features make it easy to distinguish where each block begins and ends, and nested blocks within templates become straightforward to spot. This should substantially enhance code readability.
And there's no longer a need for extraneous ng-container and ng-template wrappers for conditional HTML sections. This yields cleaner code with less boilerplate.
If only it were always that straightforward
We've covered if and for, but what about switch? Here's an example.
Enhancements Over the Prior Syntax
Mandatory track Expression for Loops
The new syntax requires a track expression that provides a unique key, linking each array item to its DOM view position for better performance, particularly with large lists.
Omitting it yields the following error:
@for loop must have a "track" expression
Additionally, Angular now employs an optimized algorithm for the for loop, minimizing DOM operations in response to collection changes, making it more efficient.
The @empty Keyword for Empty Lists
We now have an @empty keyword to handle scenarios where the list is empty, which is quite handy.
Clearer Else Clauses
As demonstrated earlier, the else clause in the old control flow syntax was not reader-friendly and demanded considerable boilerplate. With the new control flow, it's far more readable and intuitive, especially for developers new to Angular.
Integration with Async Pipe
Just as before, the async pipe remains available for subscribing to observables.
Within for loops, this is how it looks:
The pattern applies to if blocks as well:
How to Migrate
First, ensure your Angular project is on v17. Then, run the schematic below to migrate existing control flow syntax to the new style.
ng g @angular/core:control-flow-migration
When prompted for a path, provide the path to your project, and that's it.
One crucial caveat: this control flow syntax, a significant advancement for Angular, is currently in developer preview. This means internal changes may occur without following semantic versioning, giving the Angular team flexibility to address issues before it reaches general availability with the same guarantees Angular provides for all features.
Coming Up: The New @defer Syntax
Angular is also introducing a @defer syntax for lazy loading components, directives, and pipes in templates until specific conditions are satisfied. I'll explore this in the next edition of Unstacked in the coming weeks, as this post is already quite lengthy for a newsletter.
Conclusion
This post examined the new control flow syntax for Angular and its advantages over the old syntax. We saw that it is more familiar and arguably more readable, requiring less cognitive effort to understand, even for seasoned Angular developers, let alone beginners. We also noted how the new syntax not only replaces but enhances the old one, introducing helpful additions like @empty and the mandatory track expression for better performance.
That's all for now—until next time, keep learning.












