Angular 18 has an exciting new feature under development for developers: the @let
directive. This tool will help you create variables quickly and easily within HTML code. It's important to note that this feature is still being developed and has not yet been merged into a release within Angular 18. Let's understand how it works and look at some cool examples of its potential use.
Update: According to a comment by Denes Papp on dev.to, the merge has now happened in version 18.1.0, and the @let
directive is now official. For more details and useful links, you can check out his comment here. Thanks to Denes for the update!
What is @let
?
The @let
directive allows you to create variables directly in the HTML code. This means you can do simple operations like joining text or calculations without needing to write more complex code elsewhere in your program.
How to Use @let
Here’s a simple example:
<div>
@let greeting = 'Hello, ' + name + '!';
<h1>{{ greeting }}</h1>
</div>
In this example, we are creating a variable greeting
that concatenates the string "Hello, " with the variable name
, and then we display it on the screen.
Usage Examples
1. Calculating Total Prices
Imagine you have a list of products and you want to show the total price of each one. You can do it like this:
@for (product of products; track product.id) {
@let totalPrice = product.price * product.quantity;
<div>
<p>{{ product.name }} - Total: {{ totalPrice | currency }}</p>
</div>
}
Here, totalPrice
is calculated by multiplying the product’s price (product.price
) by the quantity (product.quantity
).
2. Formatting Dates
You can format dates easily. Suppose you have a list of events:
@for (event of events; track event.id) {
@let formattedDate = (new Date(event.date)).toLocaleDateString();
<div>
<p>{{ event.name }} - Date: {{ formattedDate }}</p>
</div>
}
Here, formattedDate
converts the event date (event.date
) to a more readable format.
3. Showing Messages Based on Conditions
You can create messages based on conditions, like checking if a user is active:
@for (user of users; track user.id) {
@let statusMessage = user.isActive ? 'Active' : 'Inactive';
<div>
<p>{{ user.name }} - Status: {{ statusMessage }}</p>
</div>
}
In this example, statusMessage
is set to "Active" if the user is active (user.isActive
), or "Inactive" if not.
More Complex Examples
4. Calculating Average Grades
Let’s calculate the average grades of students:
@for (student of students; track student.id) {
@let total = student.grades.reduce((sum, grade) => sum + grade, 0);
@let average = total / student.grades.length;
<div>
<p>{{ student.name }} - Average: {{ average.toFixed(2) }}</p>
</div>
}
Here, we calculate the sum of the grades (total
) and then the average (average
), displaying it with two decimal places (toFixed(2)
).
5. Filtering Items in a List
Suppose you want to show only the available products:
@for (product of products; track product.id) {
@let isAvailable = product.stock > 0;
@if (isAvailable) {
<div>
<p>{{ product.name }} - In stock: {{ product.stock }}</p>
</div>
}
}
In this case, isAvailable
checks if the product has stock (product.stock > 0
).
Benefits of @let
with | async
One of the challenges in Angular before the introduction of @let
was handling asynchronous data, especially when dealing with observables. Typically, you would use the | async
pipe, but this often required additional directives like *ngIf
to avoid undefined values, or you had to create extra components or subscribe manually in the TypeScript code.
With @let
, handling async data becomes more straightforward and elegant:
<div>
@let data = (data$ | async);
@let processedData = data ? data.map(item => item.value) : [];
<ul>
@for (item of processedData; track item) {
<li>{{ item }}</li>
}
</ul>
</div>
Here, data$
is an observable, and using @let
, we can directly process the asynchronous data within the template without needing extra directives or subscriptions. The @let
directive handles the async pipe and processes the data in a more readable and concise way.
When Not to Use @let
Although @let
is very useful, there are times when it’s not the best choice:
- Complex Logic: If the logic you need is very complicated, it’s better to do it in TypeScript, outside the template.
- Reusability: If you need to use the same logic in multiple places, it’s more efficient to create a function or method in the component.
-
Performance: In some situations, especially with many items,
@let
can impact performance. It’s important to test and make sure everything is running fast.
Conclusion
@let
in Angular 18 is a powerful and easy-to-use tool that helps simplify code. With it, you can create local variables directly in HTML, making your code cleaner and easier to understand. Use @let
for simple operations and keep complex logic in TypeScript. This way, you get the best of both worlds!
Top comments (20)
I'm wondering how will it impact component rendering. I used to use the getter method but that'd render the component any time any changes detected. I guess this is kind of same but just seems bit cleaner?
Using
@let
is a more straightforward and cleaner approach to defining temporary or calculated variables in the template, avoiding the need for getters in the component class. Both methods—getters
and@let
—have similar reactive behavior and impact the component rendering equivalently when monitored properties change. The choice between them depends on style preferences and code organization.Is it really a choice if it might be a bad practice?
Some of these examples look like they should've been written as pure pipes.
It's a little bit concerning that you didn't mention them at all.
Also the use of the legacy ngIf, ngFor etc.
Angular 17 brought us @if and @for .
I updated the article to include
@for
and@if
, but the main focus of the article is the@let
directive. My initial idea was to highlight only@let
for people coming from previous versions, as@for
and@if
are new. In any case, I've adjusted the article. Thank you!@let
has been included in Angular v18.1.0.github.com/angular/angular/release...
Here are the Github links if anyone is interested:
github.com/angular/angular/pull/56715
github.com/angular/angular/pull/55848
This closes a 7 year old issue:
github.com/angular/angular/issues/...
Wonderful, I will later make a note about your comment and inform that the @let has already been merged. Thank you very much for the comment!
Suggestion:
Maybe use
@if
instead of*ngIf
, since you are using new template syntax (@let
). Right now it's mixed, and looks a bit messy imo.Same with the for-loops
I've updated the article to include
@for
and@if
, but my initial focus was to highlight the@let
directive. Originally, I wrote the article with the intention of emphasizing@let
.Makes sense. When I was creating it, I only focused on showing the @let. I will update the new syntax for if and loops during the week. Thanks for the suggestion.
You should update the introduction as 'Angular 18 has brought' is wrong. This feature is not even merged yet.
You're right, except it's now merged but not yet part of a distributed package.
I’ve adjusted it here and highlighted this information. thanks!
What happen if in component we define a property that have same name with name of variable at template by @let?
The
fullName
used in the{{ fullName }}
interpolation refers to the locally scoped variable created by the@let
directive, not the component's property. As a result, it will display "Hello, John Doe."Without the
@let
directive, the template would default to using thefullName
property from the component, resulting in "Hello, Some other value."To summarize, the local variable defined by
@let
has priority within its scope and will override any component property of the same name in the template.absolutely amazing! long-time wanted feature
Hi Rodrigo Oler,
Top, very nice and helpful !
Thanks for sharing.
It can be really convenient when working with observable and async pipe.
who is telling you Angular Template supports the arrow function?
Did you test the last example recently? Bcs if gives u an
Parser Error: Bindings cannot contain assignments at...
error at the processedData definition.