Over the past year, I’ve been working extensively with Angular 17 and have seen firsthand how it has made significant improvements in both performance and code readability. Many of the new features in this version replace the need for external plugins by incorporating more streamlined, integrated solutions. In some cases, the new additions offer a direct 1:1 replacement for existing “ng[...]” logic, but with added enhancements that make development more efficient. In this article, I’ll share some standout features and lessons learned from my experience with Angular 17. While this overview isn’t exhaustive, it highlights the key changes that can have an immediate impact on your projects.
Deferrable Rendering
One of the cooler new features added in version 17 is the addition of the @defer directive. This new directive allows you to lazy load a section of your component based on an event. This is super handy if you have a child component that isn’t used right away and that takes a decent amount of time to load/process. The new directive also allows you to have some predefined placeholder html and html that displays while the child component is loading. All of these changes make it much easier to lazy load components and understand the UI state during the different stages of component loading. Here is a quick example of @defer in action:
@defer (on hover(loadFor)) {
<app-defer-big-component></app-defer-big-component>
}
@placeholder {
<div #loadFor>hover here to load</div>
}
@loading (minimum 4s) {
<div>....the component is loading</div>
}
That’s it; no ts file code, no special events, it’s all right in the html file. The above code will load <app-defer-big-component>
when the user hovers over the div with the loadFor id. While the component is loading the special text will be shown, in this case for a minimum of 4 seconds, which is optional.
New Flow Control Directives
The big push in Angular 17 seems to be removing the need for some commonly used external libraries. A lot of the commonly used ng[...] attributes have been replaced with built in directives. The internal versions of these attributes are faster and blend well with all of the newer directives added to the language.
@for
The @for
directive replaces the ngFor attribute that we have used for a good number of years. It basically works the same way that ngFor does, but the newer directive is far more performant. This performance is gained by requiring each element of the looped over array to have a key value; this key value can be any concrete data type, but it needs to be unique across the data set. The use of this unique key allows Angular 17 to avoid unnecessary repaints when the elements in the looped over array change. Instead of having to recreate the entire looped over content every time the array changes, the Angular engine can just add/remove/update elements as needed. The syntax for the new directive follows the same conversion as all of the other new directives, here is an example:
@for(item of allItems; track item.someItemId) {
<div>{ { item.YourPropertyValue } }</div>
}
@empty {
<div>There are no elements in your collection</div>
}
Notice something awesome about the new @for
directive? It has a built-in “empty” option that you use to display content when there are no elements in your collection. No more having extra backend logic to detect empty collections to display special content; it’s all built in. The empty option will detect an empty collection as well as undefined collections (which is pretty nice in my opinion).
@if / else
The @if
directive works the same as the ngIf attribute we are used to, but with the new ability to include an “if else” and “else” clause along with the associated if statement. Rather than having to use multiple ngIf statements or track multiple variables on the backend to control what displays in the UI, we can now use this streamlined directive. Here is an example:
@if (someControlValue == "A") {
<div>The thing is equal to A</div>
}
@else if (someControlValue == "B") {
<div>The thing is equal to B</div>
}
@else {
<div>The thing is not A or B</div>
}
Again, this new directive follows the same format as all of the other new directives, making the control flow in your HTML files easier to spot at first glance. No longer do we need to hunt for ngIf attributes buried deep in a tag with 10 other attributes, it’s right there, front and center.
@switch
@switch
is a simple switch/case control flow directive that allows for displaying different elements based on any number of possible values. It functions just like a standard switch/case/default statement, but clearly shows the different forks in the HTML instead of hiding it in overused element attributes.
@switch (switchControlVal) {
@case(3) { <span>Value for 3</span> }
@case(4) { <random-control></random-control> }
@case(5) { <h2>Because I can</h2> }
@default() { <div>Unknown</div> }
}
Nothing super special here, just your standard switch/case/default statement.
Signals
Another powerful addition in Angular 17 is the Signals feature. Signals provide a more efficient and predictable way to manage reactivity in your applications. There is no longer a need to pass around Subjects or Observables which require messy subscriptions to track state changes. Signals allow for granular state tracking, notifying consumers whenever values change, which leads to optimized rendering updates and improved performance.
With Signals, you can define both writable and computed signals. Writable signals can be updated directly using methods like .set()
, .update()
, or .mutate()
, while computed signals derive their values from other signals and update automatically when their dependencies change. For example, you can have a count signal and a doubleCount computed signal that always reflects twice the value of count.
Here’s a simple example of defining and using signals:
const count = signal(0);
const doubleCount = computed(() => count() * 2);
count.set(3); // doubleCount will automatically update to 6
Signals integrate seamlessly into templates, ensuring that any changes to signal values automatically trigger updates in the UI. This makes writing and debugging reactive code easier and more intuitive, offering a cleaner alternative to traditional observables for managing component state.
Wrap Up
Many of the new features in Angular were designed to make code more readable, quicker to implement and more performant. For the most part these new features should be easy to integrate into your project and should remove a lot of unnecessary complexity in component logic. If your application is running on an older version of Angular and you need help upgrading, give Callibrity a call. We have Angular experts that would be happy to help you navigate upgrading your application.
If you are interested in seeing some of this code in action, check out my github repo with a working project utilizing all the above features: https://github.com/armstrongsp/Angular17_Features