Built-in structural directives

Ao iniciar os estudos em Angular, aprendemos como criar Diretivas Estruturais utilizando por exemplo *ngIf e *ngSwitch para condicionais e *ngFor para iterar dinamicamente por itens de uma lista, mas para isso precisamos do CommonModule (no standalone component ou em lazy loaded modules). Vamos utilizar o exemplo a seguir a partir de uma lista de tarefas a serem feitas (Todo Items):

src/app/app.component.ts

import { Component, inject } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { HttpClient } from '@angular/common/http';
import { CommonModule } from '@angular/common';

interface Todo {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  private httpClient = inject(HttpClient);
  todos$ = this.httpClient.get<Todo[]>('https://jsonplaceholder.typicode.com/todos');
  todos = toSignal(this.todos$);
}

src/app/app.component.html

<ul>
  <ng-container *ngIf="todos(); else loading">
    <ng-container *ngIf="todos()!.length; else empty">
      <li *ngFor="let todo of todos()">
        <input type="checkbox" [checked]="todo.completed" />
        {{ todo.title }}
      </li>
    </ng-container>
  </ng-container>
    
  <ng-template #loading>
    <p>Carregando...</p>
  </ng-template>
  <ng-template #empty>
    <p>Não há todos</p>
  </ng-template>
</ul>

Podemos ver que não é possível utilizar *ngIf e *ngFor no mesmo elemento html <li>, e para não adicionarmos uma div adicional ao DOM, acabamos precisando usar <ng-container> e também <ng-template> para o fluxo de else, o que nos obriga a escrever muitas instruções adicionais no template!

New Control flow Syntax

Neste artigo vamos falar um pouco sobre algumas melhorias introduzidas a partir da v17 como Developer Preview e na v18 como stable para produção, e mostrar que embora havia uma outra forma de ser feito, as novidades ajudaram a melhorar demais a experiência nossa como desenvolvedor (DX), vamos conferir a seguir a nova sintaxe de Control Flow!

@if e @else

Com a nova sintaxe em bloco fica bem mais legível, e podemos utilizar também além do @if, @else if e @else, desta forma não precisamos mais do <ng-container> e do <ng-template>.

@for e @empty

No caso do @for agora é obrigatório o uso da expressão track (o que aumenta consideravelmente performance com um esforço reduzido), além de poder usar o @empty como sendo um "else" do for, no caso do array ser vazio, e você gostaria de renderizar uma mensagem como empty state.

Refatorando

Vamos refatorar o código abaixo trocando o *ngIf por @if e *ngFor por @for e conferir o resultado final:

src/app/app.component.ts

import { Component, inject } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { HttpClient } from '@angular/common/http';

interface Todo {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent {
  private httpClient = inject(HttpClient);
  todos$ = this.httpClient.get<Todo[]>('https://jsonplaceholder.typicode.com/todos');
  todos = toSignal(this.todos$);
}

src/app/app.component.html

<ul>
  @if (todos()) {
    @for (todo of todos(); track todo.id) {
      <li>
        <input type="checkbox" [checked]="todo.completed" />
        {{ todo.title }}
      </li>
    } @empty {
      <p>Não há todos</p>
    }
  } @else {
    <p>Carregando...</p>
  }
</ul>

Migração

Mesmo que você utilize módulos, a partir da versão v17 já pode utilizar esta nova sintaxe que além de importar arquivos javascript a menos, ainda é bem mais legível! Caso seu projeto seja grande, você pode utilizar para auxiliar o angular também já fornece o schematic ng generate @angular/core:control-flow, o link da documentação está aqui.

Compartilhe com seus amigos que gostam de se informar sobre as novidades atuais do framework e até o próximo artigo! Grande abraço!

Sugestões de assuntos? Envie aqui
Copyright © 2024 Angularizando