Sunday, November 19, 2023

Angular 17 : New control flow syntax

Angular17- New control flow

Angular 17 recently came out with several exciting updates. One notable addition is the Control Flow feature. This new feature simplifies template writing by introducing a direct way to handle control flow within the template itself. Now, there's no need to rely on directives like *ngIf, *ngFor, and *ngSwitch for control flow as this new syntax streamlines the process.

This post will demonstrate a basic project using a new control flow method, moving away from the traditional directive-based approach. You can go through my other Angular post here.Let's begin right away!

Angular Project Setup

Before we start using the new feature, let's make sure you have an Angular project set up and ready to go. If you haven't done so yet, create a new Angular project using these commands with the Angular CLI:

npm install -g @angular/cli@latest
ng new ng17-control-flows

This command creates a fresh Angular project, including all the essential files and dependencies with the latest version.

Once it's set up, open the app.component.html file and remove the default Angular code. Let's add a basic HTML structure to it instead.

<h1>NG -17 :New Control Flows</h1>

Conditionally rendered control blocks: @if and @else

Let’s start with the replacement of *ngIf.

In the first example, I create a checkbox and bind it to the isChecked property.Starting with a default value of true, the checkbox appears checked, displaying the content within the @if block.The examples below are from the app.component.html template file:

<h3>@if and @else</h3>
<div>
  <input #checkbox type="checkbox" [checked]="isChecked" (change)="toggle()" id="checkbox" />
</div>
<div>
  @if (isChecked) {
  <span>Checked</span>
  }
  @else {
  <span>Not checked</span>
  }
</div>

I use isChecked as a logical expression that gives a boolean value. Adding an @else block below @if renders when the expression in @if is false, meaning if the isChecked turns false. If I uncheck the checkbox, Angular shows the @else block content.

Switch control flow with with @switch, @case and @default

In the following example, I set up four radio buttons along with a property called radioValue. Initially, the property holds the value 1. When a user clicks on any of the radio buttons, the radioValue changes to either 1, 2, 3, or 4 depending on the selection.

<h3>@switch and @case</h3>
<div>
  <div>
    <input type="radio" [checked]="radioValue === 1" (change)="radioValueChange(1)" id="radio1" />
    <label for="radio1">1</label>
  </div>
  <div>
    <input type="radio" [checked]="radioValue === 2" (change)="radioValueChange(2)" id="radio2" />
    <label for="radio2">2</label>
  </div>
  <div>
    <input type="radio" [checked]="radioValue === 3" (change)="radioValueChange(3)" id="radio3" />
    <label for="radio3">3</label>
  </div>
  <div>
    <input type="radio" [checked]="radioValue === 4" (change)="radioValueChange(4)" id="radio4" />
    <label for="radio4">4</label>
  </div>
</div>
<div>
  @switch (radioValue) {
  @case (1) {
  <span>Case 1</span>
  }
  @case (2) {
  <span>Case 2</span>
  }
  @default {
  <span>Default case (Not 1 or 2)</span>
  }
  }
</div>

I nested three blocks into the @switch block:

  • the contents of the @case (1) { block is rendered, when the radioValue equals to 1
  • the contents of the @case (2) { block is rendered, when the radioValue equals to 2
  • the contents of the @default { block is rendered, when the radioValue doesn't equal to the values we specified in the @case blocks

Using @for blocks to render items of a collection

Let's define the items array in the component's class:

collection = [
    { id: 1, name: 'ABC' },
    { id: 2, name: 'XYZ' },
  ];

We can use an @for (item of items; track item.id) { block to render a collection's elements:

<h3>@for</h3>
<ul>
  @for (item of collection; track item.id;) {
  <li><strong>{{item.name}}</strong></li>
  }
</ul>

For each item in the collection, it's essential to have a distinct property (such as an ID) that we reference using the track argument. If the collection comprises strings or numbers instead of objects, we can directly use the item as the track value in the loop: @for (item of items; track item).

Using an @empty block to handle the empty collections passed to @for

We can include an @empty block below the @for block. The @empty block displays its content when the collection provided to the @for block is empty.

<h3>@empty</h3>
<ul>
  @for (item of emptyCollection; track item;) {
  <li><strong>{{item}}</strong></li>
  }
  @empty {
  <span>The collection is empty</span>
 }

Output

Migrate ngIf, ngFor, and ngSwitch to the new control block syntax

To convert the old structural directives in an app's templates to the new control blocks, run the following schematic:

ng g @angular/core:control-flow-migration

The full source code is available here:

Happy coding!! 😊

No comments:

Post a Comment

^ Scroll to Top