avatarFuji Nguyen

Summary

The web content provides a comprehensive guide on upgrading from Angular 16 to 17, detailing the new control flow language features, and sharing insights from the upgrade process.

Abstract

Angular 17 introduced a new feature called Angular Code Flow, which simplifies the integration of components using Angular signals. The blog post outlines a step-by-step approach to upgrading an Angular Talent Management application from version 16 to 17, including manual and automated methods for converting structural directives to the new control flow blocks. It covers prerequisites for the upgrade, such as Node.js, TypeScript, and Zone.js versions, and provides examples of refactoring code to replace ngIf and ngFor with the new @if, @else, and @for syntax. The post also discusses the use of Angular Schematics for an automatic upgrade and addresses potential issues that may arise during the transition, offering solutions to ensure a seamless upgrade experience.

Opinions

  • The author believes that the new control flow syntax in Angular 17 is more readable and intuitive, aligning closely with JavaScript and reducing the cognitive load on developers.
  • The author suggests that the new @if and @for syntax is an improvement over the previous ngIf and ngFor directives, as it is more familiar to developers and requires less frequent references to documentation.
  • There is an acknowledgment that while the upgrade schematic is effective, developers may still need to manually review and convert certain instances of ngIf to the new @if syntax to address potential errors and warnings.
  • The author emphasizes the importance of following the Angular Update Guide and reviewing the Angular 17 Upgrade Guide for a smooth transition to the new version.
  • The author encourages readers to engage with their content by following them on Medium and becoming a member to support the creation of more useful articles.

Seamless Transition: Upgrading from Angular 16 to 17, Uncovering the Latest Control Flow Language Features, and Gaining Insightful Lessons Learned.

Introduction

Angular version 17 was released on November 8, 2023, and it includes a new feature called Angular Code Flow. This new code flow is built-in to Angular and will enable simpler integration of components based on Angular signals.

In this blog post, I will provide detailed information about upgrading an Angular Talent Management application version 16 and the manual and automated approach I took to convert all the Angular components from structural directives (such as ngif, ngfor) to new code flow (@if, @for).

You can find the upgraded Angular 17 source code of the project on GitHub and the online demo here.

Content

The blog contains three parts

Part 1: Elevating Your Angular App A Step-by-Step Guide to Upgrading from Version 16 to 17

Part 2: Transitioning Structural Directives Converting Old Directives to the New Control Blocks Manually

Part 3: Seamless Transition Upgrading to New Control Flow with Angular Schematics’ Automatic Upgrade

Part 1: Elevating Your Angular App

This section provides a step-by-step guide on upgrading from Version 16 to 17, ensuring a smooth and seamless transition.

Task 1 — Install the prerequisite software

To plan for the upgrade, you can visit the Angular Update Guide and review the instructions from the Angular project team. According to the Angular 17 Upgrade Guide, there are three prerequisites to upgrade from version 16 to 17:

  1. Node Version at least ^18.13.0
  2. Typescript >=4.9.3 <5.3.0
  3. Zone.js at least ^0.14.0

Prerequisite 1: Make sure that you are using a supported version of node.js before you upgrade your application. Angular v17 supports node.js versions: v18.13.0 and newer.

To check the version of Node.js installed on your system, you can run the following command in your terminal: node -v

This will print the version of Node.js installed on your system. If you need to upgrade Node.js to the latest version, you can do so by following the instructions for your operating system on the official Node.js website.

Once you have installed the latest version of Node.js, you can verify that it has been installed correctly by running the node -v command again.

If you need to update NPM to the latest version, you can do so by running the following command in your terminal: npm install -g npm

Prerequisite 2: Make sure that you are using a supported version of TypeScript before you upgrade your application. Angular v17 supports TypeScript version 5.2 or later.

You can check the version of TypeScript in your project by looking at the devDependencies section of your package.json file. The version of TypeScript is specified as a value for the typescript key. For example, if the version of TypeScript is 4.5.4, you should see “typescript”: “4.5.4” in the devDependencies section of your package.json file.

If you need to update the version of TypeScript, you can do so by changing the value of the typescript key in your package.json file to the desired version number. Once you have updated the typescript key, you can run npm install at the command line to install the new version of TypeScript.

Prerequisite 2: Make sure that you are using a supported version of Zone.js before you upgrade your application. Angular v16 supports Zone.js version 0.14.x or later.

You can check the version of Zone.js in your project by looking at the dependencies section of your package.json file. The version of Zone.js is specified as a value for the zone.js key. For example, if the version of Zone.js is 0.14.2, you should see "zone.js": "0.14.2" in the dependencies section of your package.json file.

If you need to update the version of Zone.js, you can do so by changing the value of the zone.js key in your package.json file to the desired version number. Once you have updated the zone.js key, you can run npm install at the command line to install the new version of Zone.js.

Task 2— Upgrade to Angular v17

To upgrade your Angular 16 project to Angular 17, you can use the ng update command. If you encounter any issues, you can try adding --force flag to the command. Here are the steps you can follow:

Step 1: Update your Angular CLI to version 17 by running the following command:

ng update @angular/cli@17

If you encounter any issues, you can try adding — force flag

ng update @angular/cli@17 --force

Step 2: Update your Angular core packages by running the following command:

ng update @angular/core@17

This will update all of your Angular core packages to the latest version, including @angular/core, @angular/compiler, and @angular/platform-browser.

Step 3: Update your Angular schematics packages:

ng update @angular-eslint/schematics@17

Step 4: Optionally, if you are using any other third-party packages, you will need to update them individually. Here is an example of the update @ng-bootstrap/ng-bootstrap to version 16.0.0.

ng update @ng-bootstrap/ng-bootstrap@16.0.0

Part 2: Transitioning Structural Directives

This section guides you through the manual conversion of old directives to the new control blocks.

Angular 17’s revamped control flow syntax provides numerous advantages compared to the previous version. It’s more familiar, subjectively more readable, and demands less mental effort for comprehension, even among seasoned developers. Aligning closely with JavaScript, the new syntax is more intuitive, reducing the need for frequent documentation references.

Let’s go over examples of old vs new syntax.

Example of refactoring ngif

Here is an example of how ngIf was used in Angular 16:

        <div class="float-left">
          <!-- HTML markup for Create button -->
          <button
            (click)="onCreate()"
            class="btn btn-primary w-20"
            type="submit"
            [disabled]="entryForm.invalid || !isAddNew"
            *ngIf="this.isAddNew"
          >
            <span translate><i class="fas fa-plus"></i> Save</span>
          </button>
          <!-- HTML markup for Update button -->
          <button
            (click)="onUpdate()"
            class="btn btn-primary w-20"
            type="submit"
            [disabled]="entryForm.invalid || isAddNew"
            *ngIf="!this.isAddNew"
          >
            <span translate><i class="fas fa-edit"></i> Update</span>
          </button>
          <!-- HTML markup for Delete button -->
          <button
            (click)="onDelete()"
            class="btn btn-danger w-20"
            type="submit"
            [disabled]="entryForm.invalid || isAddNew"
            *ngIf="!this.isAddNew"
          >
            <span translate><i class="fas fa-trash-alt"></i> Delete</span>
          </button>
        </div>

The *ngIf directive is used to conditionally render the button element. The isAddNew property is used as the condition. For example, if isAddNew is true, the button element will be rendered; otherwise, it will not be rendered.

Here is the refactored code of how new@if and @else can be used to replace ngIf in the given HTML code snippet:

        <div class="float-left">
          <!-- HTML markup for Create button -->
          @if (this.isAddNew) {
          <button
            (click)="onCreate()"
            class="btn btn-primary w-20"
            type="submit"
            [disabled]="entryForm.invalid || !isAddNew"
          >
            <span translate><i class="fas fa-plus"></i> Save</span>
          </button>
          } @else {
          <!-- HTML markup for Update button -->
          <button
            (click)="onUpdate()"
            class="btn btn-primary w-20"
            type="submit"
            [disabled]="entryForm.invalid || isAddNew"
          >
            <span translate><i class="fas fa-edit"></i> Update</span>
          </button>
          <!-- HTML markup for Delete button -->
          <button
            (click)="onDelete()"
            class="btn btn-danger w-20"
            type="submit"
            [disabled]="entryForm.invalid || isAddNew"
          >
            <span translate><i class="fas fa-trash-alt"></i> Delete</span>
          </button>
          }
        </div>

The @if/@else syntax is used to conditionally render the button element. The isAddNew property is used as the condition. If isAddNew is true, the first button element (for saving a new record) will be rendered; otherwise, the second button (for updating an existing record) and the thirdbutton (for deleting an existing record) element will be rendered.

Example of refactoring ngfor

Here’s a code walkthrough for the ngFor directive in the given HTML code snippet in Angular 16:

        <tbody *ngIf="positions?.length !== 0">
          <tr *ngFor="let position of positions" (click)="wholeRowClick(position)">
            <td>
              {{ position.positionNumber }}
            </td>
            <td>{{ position.positionTitle }}</td>
            <td>{{ position.positionDescription }}</td>
            <td>{{ position.positionSalary }}</td>
          </tr>
        </tbody>
        <tbody *ngIf="positions?.length === 0">
          <tr>
            <td colspan="3" class="no-data-available">No data!</td>
          </tr>
        </tbody>

The ngFor directive is used to iterate over an array of positions and display the data in the UI. The *ngFor directive is used to create a template for each item in the array. In this case, the *ngFor directive is used to create a table row for each position in the positions array.

Here is the refactored code of how @for can be used to replace ngforin the given HTML code snippet:

        <tbody>
          @if(positions.length !== 0) { @for(position of positions; track position.id) {
          <tr (click)="wholeRowClick(position)">
            <td>
              {{ position.positionNumber }}
            </td>
            <td>{{ position.positionTitle }}</td>
            <td>{{ position.positionDescription }}</td>
            <td>{{ position.positionSalary }}</td>
          </tr>
          } } @else {
          <tr>
            <td colspan="4" class="no-data-available">No data!</td>
          </tr>
          }
        </tbody>

The @for directive is used to iterate over an array of positions and display the data in the UI. The @for directive is used to create a template for each item in the array. In this case, the @for directive is used to create a table row for each position in the positions array.

Part 3: Seamless Transition

This section delves into the process of upgrading to the new control flow using Angular Schematics’ automatic upgrade, simplifying the transition for a more efficient workflow.

ng g @angular/core:control-flow is a schematic that can be used to convert the old structural directives in an app’s templates to the new control blocks introduced in Angular 17. The new control flow syntax includes new “if-then-else” syntax, “for” loop syntax, and “switch-case” syntax 1.

As of the current writing, the upgrade schematic effectively handles the upgrade process for ngIf and ngFor directives. However, for refactoredngIf, developers may need to review and streamline the code by incorporating @else or @else if where necessary to avoid repetitive code.

Lesson Learned

When I performed the project automatic upgrade using ng g @angular/core:control-flow, it overlooked certain instances of NGIF in the codebase. Running ng serve may trigger the warning error mentioned below.

warning NG8103: The `*ngIf` directive was used in the template, but neither the `NgIf` directive nor the `CommonModule` was imported. Use Angular’s built-in control flow @if or make sure that either the `NgIf` directive or the `CommonModule` is included in the `@Component.imports` array of this component.

To address this issue and resolve the error, you will need to manually convert instances of NGIF to the new @if syntax. Take the following steps:

  1. Identify NGIF Instances: Scan your project codebase to locate all occurrences of NGIF. This can be done using a code editor’s search functionality or an integrated development environment (IDE).
  2. Replace with @if: For each instance of NGIF, replace it with the equivalent @if syntax. The new control flow language utilizes @if for conditional rendering. Ensure that you update the syntax according to the specific conditions and logic in your application.

Recommended Contents

  1. Angular Advanced UI: Combo Box with Ng-Select Typeahead Search and Rating Component in Reactive Form
  2. Implement Toast with Bootstrap 5 in Angular 15 or 16
  3. Angular 16 Reactive Form and Validation
  4. What are Template and Reactive forms in Angular?
  5. Load Angular Component into Bootstrap Modal
  6. How to create Bootstrap modal dialog in Angular

Summary

Embarking on the journey from Angular 16 to 17 is an exciting adventure! Dive into the process with confidence by exploring the new schematic, ng g @angular/core:control-flow. This tool not only streamlines the upgrade but also offers a fantastic opportunity to refine your coding skills. Refactor those old directives, embrace the enhanced control flow, and witness a boost in code readability. Wishing you the best of luck on your upgrade project — enjoy the positive transformation!

Thanks for reading! Hope you found it useful. Want more? Please follow me and become a member on medium for more articles. With your support, I’ll keep creating awesome content for you. Have a great day ahead! — Fuji Nguyen

Angular
Upgrade
Open Source
Recommended from ReadMedium