Minha experiência para aprender Angular: onde estou agora?

ananopaisdojavascript - Mar 26 - - Dev Community

Olá! Que legal que você está aqui! 🤗
Em 2021 escrevi um artigo sobre minha experiência para aprender Angular que está disponível no Blog da Zup e que você pode ler clicando aqui 👈.
Esse singelo texto é uma atualização do meu artigo. Quem está começando no Angular nesse momento provavelmente se deparou com mudanças importantes. A maior delas é que os módulos não existem mais (pelo menos a partir da versão 17)!

Avisos!!! 🚨🚨

  1. Esse artigo será um pouco longo, portanto se você não gosta de textos longos, cai fora!!!

  2. Esse texto não foi gerado por inteligência artificial! Eu garanto! 😉

Como assim sem módulos?!?!

No artigo anterior, expliquei que os componentes (que continuam sendo a base do Angular) precisavam ser colocados em módulos para que pudessem aparecer na tela. Inclusive podíamos criar outros módulos para serem usados no módulo principal. Agora que os módulos "desapareceram", é possível importar um componente diretamente em outro componente.

O que?!?!

É isso mesmo que você leu! Os componentes, a partir de agora (quer dizer, começou na versão 15 em caráter de experimentação) são independentes (standalone)!

Agora complicou tudo!!! 😫

Então vamos com muita calma.
Nas versões anteriores tínhamos a seguinte estrutura de arquivos dentro do componente principal (a pasta app):

Antiga estrutura de arquivos do Angular

Essa estrutura também se modificou:

Nova estrutura de arquivos do Angular

Vejamos como ficou a estrutura do arquivo app.component.ts:

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

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {

}
Enter fullscreen mode Exit fullscreen mode

Aqui aparecem todos os elementos do componente que comentei no artigo anterior (selector, templateUrl, styleUrls) e mais dois elementos novos:

  • standalone: true (Quer dizer que o componente é independente)
  • imports: [] (É o vetor que vai receber as importações)

No mais continua tudo igual, temos o decorador @Component e a classe que vai conter o comportamento do nosso componente.

Nossa! Que legal!! Mas...

... Eu ainda uso as versões anteriores. Como eu vou usar esse tipo de componente?! 🧐

Se você usa as versões 15 ou 16, tem algumas alternativas:

1) Se você já está trabalhando em um projeto Angular que ainda tem @NgModules, será necessário fazer o seguinte:

  • Apagar todos os arquivos que tem o nome nome-do-arquivo.module.ts.
  • Mudar as estruturas dos arquivos .ts para a estrutura nova mostrada anteriormente.
  • Criar componentes novos com o seguinte comando no terminal:
ng generate component nome-do-componente --standalone
Enter fullscreen mode Exit fullscreen mode

Bem trabalhoso, não? 😣

2) Se você vai criar um projeto Angular do zero, use o seguinte comando no terminal:

ng new nome-do-projeto --standalone
Enter fullscreen mode Exit fullscreen mode

O seu projeto vai nascer standalone, sem necessidade de executar os passos anteriores (se você já usa a versão 17, não precisa fazer nada disso!).

Vamos ao exemplo!!

No artigo anterior, usei um exemplo bem simples (um contador) para mostrar o funcionamento básico do Angular. Vou usar o mesmo contador para mostrar uma funcionalidade que tem dado o que falar: o signal.

Grupo de Kpop Twice cantando Signal

Mas não é esse "signal" aqui! (Entendedores e fãs de Twice entenderão!) 😅 🍭

Um signal é uma função que reage à mudança de estado das informações.

Socorro!! Não estou entendendo nada!! 😰

Quer fazer o favor de se acalmar?!?!?!
Antes de mergulhar no exemplo com o signal, devemos (tentar) entender em primeiro lugar o que é gerenciamento de estado e, para tal, vou usar um exemplo do mundo real: o estado da água.

Se você não faltou à aula de ciências (realmente espero que não!), aprendeu que a água pode passar por três estados:

Estado sólido: é a água das geleiras, do pico das montanhas.
Estado líquido: é a água dos rios, lagos, mares e oceanos.
Estado gasoso: é a água que está na atmosfera.

Estados da água

E quais são os processos que fazem a água passar de um estado para outro?

Fusão: passagem do estado sólido para o líquido
Vaporização: passagem do estado líquido para o gasoso
Solidificação: passagem do estado líquido para o sólido
Condensação: passagem do estado gasoso para o líquido
Sublimação: passagem do estado sólido para o gasoso

Mudanças dos estados da água

Texto no qual retirei as informações:

Estados físicos da água e suas mudanças (Escola Kids) 👈

Como esse conceito se aplica dentro da programação?!

O estado é a condição atual de um aplicativo, que pode ser modificada ao longo do tempo.

E como o conceito de estado pode ser usado no Angular?!?!

Com relação ao Angular, o estado refere-se aos dados e informações que são usados e compartilhados entre componentes, serviços e módulos do projeto. Sabemos que os componentes são a base de um projeto no Angular. Esses componentes precisam acessar e modificar os dados (e consequentemente o estado de uma parte do aplicativo). Nesse caso, o gerenciamento de estado fornece um modo organizado de lidar com esses dados, certificando-se de que estejam consistentes e acessíveis por todo o projeto. Os dados que podem ser armazenados, atualizados e lidos ficam em um local centralizado conhecido como contêiner de estado, que detém o estado do aplicativo e fornece métodos para interagir com ele. Essa centralização permite que vários componentes possam acessar e modificar os dados de modo previsível e consistente.

Quais são as vantagens?!

  • Compartilhamento de dados entre componentes com base nas interações do usuário
  • Manuseio de estados complexos do aplicativo
  • Fluxo de dados previsível
  • Responsabilidades separadas

Voltando ao nosso exemplo do contador...

O componente está criado e a estrutura inicial é essa:

import { Component } from '@angular/core';

@Component({
  selector: 'counter',
  standalone: true,
  templateUrl: './counter.component.html',
  styleUrls: ['./counter.component.css'],
})
export class CounterComponent {

}
Enter fullscreen mode Exit fullscreen mode

Agora vamos importar o contador diretamente no arquivo app.component.ts:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CounterComponent } from './counter/counter.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, CounterComponent],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {

}

Enter fullscreen mode Exit fullscreen mode

Nosso componente vai aparecer no HTML dessa forma:

<counter />
Enter fullscreen mode Exit fullscreen mode

Voltando ao arquivo counter.component.ts, vamos importar o signal para usar no nosso componente:

import { Component, signal } from '@angular/core';
Enter fullscreen mode Exit fullscreen mode

Vamos definir uma função signal cujo valor (estado) inicial é 0:

value = signal(0);
Enter fullscreen mode Exit fullscreen mode

Esse valor será mostrado no HTML da seguinte forma (não se esqueça de estamos lidando com uma função e precisa ser chamada como tal):

<h2>{{ value() }}</h2>
Enter fullscreen mode Exit fullscreen mode

Vamos criar dois botões para aumentar e diminuir o valor do contador:

<button>Aumentar</button>
<button>Diminuir</button>
Enter fullscreen mode Exit fullscreen mode

No arquivo counter.component.ts, vamos criar dois métodos para aumentar e diminuir o valor inicial. E é aqui que o signal se destaca! Ao clicar no botão de aumentar ou diminuir o signal avisa que o estado do valor configurado foi alterado pelos eventos de clique no botão.

E como esse estado será alterado? 🧐

O estado será alterado com .set() ou .update()

Qual é a diferença?!

O .set() altera diretamente um valor, enquanto que o .update() usa uma função de callback para atualizar um valor.

// Exemplo com .set()
  increment() {
    this.value.set(this.value() + 1);
  }

  // Exemplo com .update()
  decrement() {
    this.value.update((num) => num - 1);
  }
Enter fullscreen mode Exit fullscreen mode

Agora vamos usar esses métodos nos nossos botões

<button (click)="increment()">Aumentar</button>
<button (click)="decrement()" [disabled]="value() === 0">Diminuir</button>
Enter fullscreen mode Exit fullscreen mode

No botão de diminuir coloquei uma condição para desabilitá-lo quando o valor voltasse ao estado inicial, que é 0

Essa é a aparência final do nosso contador:

De 2021 até agora: onde estou?

Como havia dito no artigo anterior, bati a cabeça por muito tempo até entender os conceitos básicos do Angular. Ao estudar essas novas funcionalidades, tive a sensação de ter voltado à estaca zero, pois eu havia me acostumado com uma estrutura (com os módulos) e agora tenho que trabalhar com uma estrutura completamente diferente (sem os módulos)!

Tudo que foi explicado aqui está muito simplificado, porque:

1) Gostaria de ajudar quem está começando
2) Para que alguém possa passar por menos perrengues

Aprender Angular é um desafio que ainda vale a pena!!

Até a próxima! 🤗

Referências 📚

Linkedin: Techniques to manage state in angular and witch one we should use (Salem Naser) 👈

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .