Lang
Blog

Angular 17: New Changes You Should Know

ByNitesh Agrawal
March 29th . 7 min read
Angular 17 - New Changes You Should Know

Google has rolled out Angular’s latest version last November i.e. Angular 17. On this date when we are writing this article, Angular 17 is still in Beta Phase. With this release there are many changes that have been introduced.

In this article, we will explore the most significant changes in Angular’s new version that you should know to stay up to date. Let’s Start...

Angular-1.jpg

Do you know that Angular has a new look?

Angular has updated its Old Document website with a totally new and Vibrant website and a brand-new Logo.

  • You can access old website here.
  • You can Access New Website here.

Angular Playground

Angular has Integrated a playground (let’s call it Angular Playground) to play with code directly on its new website. This will help developers to practise angular without installing the angular environment in real system.

Angular Standalone Components

From Angular 17, standalone components are default. So basically, you don’t need the ngModule and other modules to import something. you can directly import things like FormsModule into component. Components can be converted to non-standalone by setting standalone to false.

@Component({
  selector: 'profile-photo',
  templateUrl: 'profilePhoto.html',
  styleUrl: 'styles.css',
  Standalone: true  // this line can be used to set component as standalone or non-standalone
})

Lazy loading components in Angular?

As we already know that angular provides lazy loading feature in which we had to call our module using loadchildren property. Now with new angular 17 feature, we can lazy load component directly.

You can perform lazy loading for a component using the following Code.

Keep in mind that Component should be a standalone component to use lazy loading on a component.

export const routes: Routes = [
    {
        path:'home',
        loadComponent: () => import('./components/home/home.component').then((item)=>item.HomeComponent),
    }
];

Angular Declarative Control Flow & Deferrable Views

Now let’s talk about major changes in Angular 17 we are getting. While the *ngIf structure has been a standard for conditional rendering, Angular 17 introduces a syntax more like JavaScript.

The new declarative control flow adds the functionality of *NgIf, *NgFor, and *NgSwitch into the framework itself and Angular @defer allows templates to load content lazily, in response to one or more configurable trigger conditions.

Let’s explore the changes in these structures with an example.

<div *ngIf="user.isHuman">
  <human-profile [data]="user" />
</div>

We had to use above syntax to render data conditionally, but issue is that it will just hide or show data, it will still load it. so angular in v17 did something amazing ; they added “@defer” to lazy load the content as well.

Check the below example:

@if (user.isHuman) {
  <human-profile [data]="user" />
} @else if (user.isRobot) {
  <!-- robot users are rare, so load their profiles lazily -->
  @defer {
    <robot-profile [data]="user" />
  }
  @error {
    <span>Error</span>
  }
  @loading(minimum 1s) {
    <span>Loading...</span>
  }
} @else {
  <p>The profile is unknown!
}

In above example you can see three things which were not there in angular 16 or before, first angular introduced @if, @else syntax which is more known to us and second @defer block which can load the content on demand.

Third thing is @loading block which can be used to show loading message. In above example until “user.isRobot” condition isn’t true, <robot-profile> won’t even load. so, it will help rendering faster.

We will talk about both things. Let’s start with what is @defer

Using @defer with declarative trigger condition

Deferred blocks support the given trigger types:

  • on Interaction
  • on Hover
  • on Idle
  • on Timer
  • on Viewport

Now let’s see example for each condition.

@defer on Interaction

Angular renders the “on interaction” block, when the user interacts with its @placeholder block. method of interaction can be a click or any input events, like keypress or keyup:

@defer (on interaction) {
  <span>span is clicked</span>
}
@placeholder {       // when user will interact with this placeholder 
 <span>Placeholder (click on it!)</span> // then defer block will be shown.
}

@defer on Hover

Angular displays the “on Hover” block, when the user hovers over its placeholder block or content.

@defer (on hover) {
  <span>Hovered</span>
}
@placeholder {
  <span>Placeholder (hover it!)</span>
}

@defer on idle

Angular shows the “on idle” block Content, when the browser reaches an idle state once the page has been loaded:

@defer (on idle) {
  <span>Browser has reached an idle state</span>
}
@placeholder {
  <span>Placeholder</span>
}

@defer on timer

Angular displays the “on timer” block, when the specified time is completed. this is something like “setTimeout” which you have used in JS.

@defer (on timer(5s)) { // we can set time to lazy load this block
  <span>Visible after 5s</span>
}
@placeholder {
  <span>Placeholder</span>
}

@defer on viewport

Angular renders the “on viewport” block Content, when the placeholder enters the browser's viewport.

@defer (on viewport) {
  <app-c2 text="The block entered the viewport"/>
}
@placeholder {
  <span>Placeholder</span>
}

Prefetching

We can also use prefetching with another condition. For example, we are using on Interaction condition for defer block, but we can also prefetch the data using addition @defer condition like on hover or on timer.

In the below example the data will be fetched as soon as we will hover on the placeholder, but it will show the placeholder because our @defer block will be shown when we will interact with it. This can be helpful if we are dealing with heavy data.

@defer (on interaction; prefetch on hover) {
  <app-c3/>
}
@placeholder {
  <span>Placeholder (hover it, then click on it!)</span>
}

Now Let’s talk about the new *ngIf syntax

As you know previously in angular, we were using ng-template to achieve conditional rendering.

Let’s see the below example to understand the difference between new and old syntax:

// the old one
<div *ngIf="isTrue; else other">
this is true
</div>
<ng-template #other>
  This is not true!
</ng-template>

Now angular has updated its syntax to more familiar version which we know:

// the new one
@if (isTrue) {
  <p>This is true</p>
} @else {
  <p>This is not true</p>
}

New *ngSwitch syntax

Angular did not stop with if-else but if went ahead and update the *ngSwitch syntax as well. With new syntax it is easier to use or show content and here is how you can use the new *ngSwitch syntax

Let’s take a look at the example for both old & new syntax:

// the old one
<div [ngSwitch]="animal">
  <p *ngSwitchCase="'monkey'">You selected a monkey.</p>
  <p *ngSwitchCase="'donkey'">You selected a donkey.</p>
  <p *ngSwitchCase="'elephant'">You selected an elephant.</p>
  <p *ngSwitchDefault>Unknown Animal.</p>
</div>
// the new one
@switch (animal) {
  @case ('monkey') { <p>You selected a monkey.</p> }
  @case ('donkey') { <p>You selected a donkey.</p> }
  @case ('elephant') { <p>You selected an elephant.</p> }
  @default { <p>Unknown Animal.</p> }
}

New *ngFor syntax

Obviously now angular can’t forget *ngFor while updating other Angular Structural Directives.

Here is what angular changed with its *ngFor syntax: Suppose we have an array for animals; For example

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'control-flows-ng17';
  animals: string[] = ['Monkey', 'Donkey', 'Elephant'];
}

Now if we want to iterate over the array of animals using *ngFor then we could do it in following way:

// the old way
<p>Iterating over array of animals </p>
<div *ngFor="let animal of animals">
  <ul>
    <li>{{animal}}</li>
  </ul>
</div>

Now here comes the new way:

// the new way
<h1>Let's see the new way</h1>
@for (animal of animals; track $index) {
  <ul>
    <li>{{animal}}</li>
  </ul>
} @empty {
  Empty list of animals
}

Angular’s new @for loop also allows easy handling for collections with zero items through an optional @empty block. So, if we don’t have any Data in our array, we can just show a message.

Try latest Angular Control Flow

To try latest Angular control flow in your existing project, please use given command:

ng generate @angular/core:control-flow

Conclusion

As we saw there are many new changes in angular 17.

Among which control flow and deferrable Views looks really promising which can help our website feels faster and handling content is pretty much easy now. Apart from these, you should make the habit of using lazy loading of components too.

Please let us know your thoughts. Thanks for reading so far!

Share:
0
+0