Alura > Cursos de Front-end > Cursos de Angular > Conteúdos de Angular > Primeiras aulas do curso Angular: templates com bindings, control flow e pipes

Angular: templates com bindings, control flow e pipes

Construindo formulários com Two-way binding - Abertura

Apresentando o curso e o instrutor

Olá! Bem-vindos a mais um curso da Alura. Aqui, aprenderemos sobre templates e controle de fluxo. Sou o professor Ariel Paixão.

Audiodescrição: Ariel é um homem de pele morena, veste uma camiseta preta e usa óculos prateados.

Falando um pouco mais sobre mim, sou uma pessoa desenvolvedora full stack, ou seja, gosto de trabalhar em todas as áreas do sistema, mas a área que mais me agrada é o front-end. Também colaborei na elaboração de um curso técnico do Senai, um feito que carrego com muito orgulho.

Introduzindo o conteúdo do curso

E aqui, o que aprenderemos? Sabemos que um sistema possui telas dinâmicas, que mudam o tempo todo.

Neste curso, abordaremos como criar um sistema que se adapta a diferentes condições. Por exemplo, em um determinado sistema, ao acessar, podemos ver opções e promoções específicas, enquanto outra pessoa, acessando de outro local ou estado, visualiza promoções diferentes. Como gerenciar esse conteúdo?

Explorando as ferramentas e requisitos do curso

Para isso, aprenderemos sobre o binding de propriedades e o two-way binding (vinculação bidirecional), o novo controle de fluxo do Angular, templates e também pipes (filtros), para formatar todos os valores que aparecem na tela. Sabemos que o importante não é apenas o que aparece, mas também como aparece.

Os requisitos prévios para este curso são conhecimentos básicos de HTML, CSS e JavaScript, para que possamos combinar essas tecnologias e entender e aplicar o Angular durante as aulas.

Agradecemos e desejamos uma excelente jornada. Até breve!

Construindo formulários com Two-way binding - Apresentando o Two-Way Binding

Contextualizando o projeto Climap

Vamos contextualizar o projeto que utilizaremos durante nosso curso. Estamos analisando o Climap. Na tela inicial, temos a tela de boas-vindas, onde o projeto é apresentado e podemos entender mais sobre ele. Ao clicar no botão "entrar", somos redirecionados para a tela inicial, como podemos ver na barra de navegação. Nessa tela, podemos visualizar todas as cidades turísticas disponíveis e, de forma resumida, algumas informações sobre cada localidade e destino turístico. Há um campo de busca para procurar pelo nome da cidade e vários destinos. Temos o nome do destino e a temperatura local no momento. Vamos clicar em Florianópolis, por exemplo. Ao clicar, somos redirecionados para outra tela, a tela de detalhes, como aparece na barra de navegação. Nela, temos a barra de detalhes, barra Florianópolis, pois foi a cidade selecionada. Aqui, encontramos informações detalhadas sobre o destino, como o nome da cidade, o nome do estado, informações de temperatura mais detalhadas, incluindo umidade, temperatura mínima e máxima, e previsão para os próximos dias. No lado direito da tela, há uma seção para configuração de notificações. A ideia é que a pessoa usuária possa se inscrever em um boletim informativo para ser atualizada. Sempre que a temperatura do destino mudar, será notificada por e-mail. Além de inserir o e-mail, é possível configurar alertas, como receber a previsão para quatro dias à frente, saber a temperatura atual e futura, receber alertas de chuva, escolher a unidade de temperatura (Celsius ou Fahrenheit) e personalizar conforme suas necessidades.

Essa é nossa aplicação: simples, com três telas, mas bastante completa para o propósito que busca resolver. Agora, vamos ver como essa tela e o projeto estão estruturados no código. Estamos na tela inicial e vamos abrir nosso código para visualizar a estrutura. Estamos com o projeto de front-end em Angular aberto e, ao abrir a pasta src, encontramos outra pasta chamada "app". Dentro dela, há duas pastas importantes: a pasta "data", que contém um arquivo com todas as informações das cidades que vimos. Se quisermos alterar o arquivo cities.ts dentro da pasta "data", veremos essas mudanças refletidas nas telas, ou seja, todas as informações aparecem na nossa aplicação front-end.

Definindo tipos de dados no projeto

Para entender melhor como as informações das cidades são estruturadas, vamos dar uma olhada no tipo de dados que estamos utilizando. Primeiro, definimos os tipos para os dados de previsão e cidade:

export type ForecastDay = {
  label: string;
  date: string;
  min: number;
  max: number;
}

export type City = {
  id: string;
  name: string;
  current: number;
  condition: string;
  humidity: number;
  min: number;
  max: number;
  todayLabel: string;
  todayDate: string;
  forecast: ForecastDay[];
};

Esses tipos nos ajudam a garantir que os dados que manipulamos estão no formato correto. Agora, vamos ver como esses dados são utilizados na nossa aplicação.

Além da pasta "data", temos a pasta "pages", que é crucial, pois ao abri-la, podemos visualizar as três telas que acabamos de ver: a tela de introdução, onde a pessoa usuária é recebida; a tela inicial, onde é possível visualizar todos os destinos e uma breve informação sobre eles, como a temperatura; e a tela de detalhes, que mostra informações detalhadas do destino. Aqui está a separação de cada uma dessas páginas no código.

Explorando a estrutura do projeto em Angular

Se abrirmos a tela de detalhes, por exemplo, veremos que cada página segue a estrutura padrão do Angular, com três arquivos: HTML, TypeScript e CSS. Todas as pastas do projeto seguem essa estrutura, que é importante para o padrão Angular. Agora que conhecemos a estrutura do projeto, vamos entender o que faremos na aula de hoje. Hoje aprenderemos a utilizar o two-way binding (vinculação bidirecional). Para que serve o two-way binding? Vamos contextualizar: na tela de detalhes, ao clicar na cidade de Florianópolis, temos o campo "escreva seu e-mail" para se inscrever nas atualizações. A questão é: hoje, se escrevemos nosso e-mail e clicamos em enviar, o que acontece? Ao clicar em enviar, aparece "cadastro realizado", mas há um espaço vazio. Esse espaço deveria mostrar o e-mail digitado, como "arielpaixão10@gmail.com", mas não aparece, pois o campo existe apenas no HTML. Precisamos fazer com que o campo no HTML envie a informação para nosso arquivo TypeScript, para que a informação digitada seja reconhecida.

No front-end, geralmente utilizamos três tecnologias: HTML, CSS e TypeScript. O HTML dá a estrutura da página, o CSS a estética, e o TypeScript dá vida à página, processando e interagindo com a pessoa usuária. Atualmente, o campo de entrada de e-mail está apenas no HTML, mas precisamos transferir a informação digitada para nosso arquivo TypeScript, para que o dado seja utilizado corretamente. Vamos entender como fazer isso. Temos o campo "inscreva-se para atualizações", onde podemos escrever nosso e-mail. Vamos encontrar esse campo no arquivo HTML. Vamos abrir o código, acessar o arquivo details.component.html, já que estamos na tela de detalhes. No arquivo HTML, na linha 67, encontramos o campo. O placeholder "escreva seu e-mail" é o texto que aparece na tela, exatamente o campo que temos na página de detalhes. Identificamos o campo, mas como fazer a comunicação com o details.component.ts, que dará vida ao campo? Nossa classe de detalhes, uma classe Angular normal, já possui uma propriedade chamada email, uma variável onde guardaremos o e-mail digitado. Já temos quase tudo estruturado. O que falta? Falta fazer o binding, o fluxo que transmitirá a informação do HTML para o arquivo TypeScript. Como fazer isso? É simples: no campo de entrada de e-mail, podemos adicionar a seguinte sintaxe de Angular para usar o two-way binding.

Explicação sobre o uso do ngModel no Angular

Vamos discutir o uso do ngModel no Angular. O ngModel é utilizado para vincular dados entre o HTML e o arquivo TypeScript. Para isso, precisamos especificar a propriedade onde queremos armazenar o valor digitado. Por exemplo, se já tivermos uma propriedade chamada email no nosso arquivo TypeScript, podemos utilizá-la para armazenar o valor.

Se estivermos criando uma aplicação do zero e precisarmos de uma nova propriedade, basta adicioná-la na classe do arquivo TypeScript. Suponhamos que estamos desenvolvendo uma aplicação de pedidos de comida. Podemos adicionar uma nova propriedade chamada pedido e inicializá-la conforme necessário. No nosso caso, a propriedade email já foi criada previamente para agilizar o processo.

Agora, voltando ao HTML, na linha 67, dentro do ng-model, adicionamos a propriedade email. Após salvar o código, o ng-model deve funcionar corretamente, desde que o FormsModule esteja importado no arquivo details.component.ts. Caso contrário, o HTML não entenderá o ng-model, pois é uma sintaxe específica do Angular.

Para garantir que tudo funcione, precisamos importar o FormsModule no arquivo details.component.ts. Se não estiver importado, o ng-model não funcionará. No Visual Studio Code, ao digitar FormsMod, ele sugere a importação do FormsModule do @angular/forms. Ao clicar na sugestão, a importação é feita automaticamente.

Com o FormsModule importado, o código deve funcionar corretamente. O ng-model permite o two-way data binding, ou seja, a conexão entre o HTML e o arquivo TypeScript. Quando digitamos algo no campo de entrada no HTML, o Angular, através do ng-model, transmite essa informação para a propriedade email no arquivo TypeScript.

Ao clicar no botão na linha 69, que chama o método subscribe, o método exibe um alerta na tela com a mensagem "cadastro realizado" e o e-mail digitado. Isso demonstra o funcionamento do two-way data binding, onde a informação é transmitida do HTML para o TypeScript.

Para entender por que é chamado de two-way data binding, consideremos que a informação pode fluir em ambos os sentidos. No exemplo, ao preencher o campo de e-mail no HTML, o ng-model envia a informação para o TypeScript. O fluxo contrário ocorre quando, no arquivo details.component.ts, inicializamos a propriedade email com um valor de teste. Ao recarregar a página, o campo de e-mail já aparece preenchido, demonstrando o fluxo de dados do TypeScript para o HTML.

Portanto, o two-way data binding permite a troca de informações entre o HTML e o TypeScript, possibilitando a criação de aplicações dinâmicas e interativas.

Construindo formulários com Two-way binding - Uso correto do Two-Way Binding em formulários

Explorando o uso do ngModel em formulários

Agora, vamos explorar como podemos utilizar o ngModel dentro de formulários. No exemplo anterior, não utilizamos formulários, que é uma forma de fazer, mas na internet, no desenvolvimento web, é muito comum o uso de formulários. Vamos ver como podemos utilizar o ngModel dentro de formulários também.

Para isso, vamos ao nosso código. No arquivo details.component.html, faremos o seguinte: basicamente, vamos converter este div, este template, em um formulário. No arquivo details.component.html, na linha 65, vamos transformar este div, que contém a classe NewsletterArea, em um form, ou seja, em um formulário.

<form class="newsletter-area">
    <label for="newsletter-email">Inscreva-se para atualizações:</label>
    <input id="newsletter-email" name="email-newsletter" type="email" placeholder="Digite seu e-mail"
        [(ngModel)]="email" />
    <button class="newsletter-button" type="button" (click)="subscribe()">
        Enviar
    </button>
</form>

Ajustando o botão e o evento de envio

Além disso, ao mudar este div, faremos o seguinte: vamos pegar o button, aquele botão que tem "enviar", da linha 69. Aqui, no seu tipo, mudaremos para Submit e removeremos o click Subscribe. Para onde vai isso? Esse click Subscribe, que é o gatilho para que nosso método em TypeScript seja executado, será transferido para o formulário. Ou seja, na tag form, vamos adicionar ngSubmit, e aqui dentro, sim, colocaremos o método Subscribe.

<button class="newsletter-button" type="submit">
    Enviar
</button>

Transformamos nosso div em formulário e também o botão. Mudamos o tipo aqui, colocando type="Submit" em vez de type="button", e também, onde havia um click Subscribe, movemos essa informação para cima. Agora, essa informação aparece aqui: ngSubmit, Subscribe.

<form class="newsletter-area" (ngSubmit)="subscribe()">

Testando o formulário e a importância do atributo name

Vamos testar se funciona? Converti isso em um formulário. Em teoria, se mudarmos aqui, colocando "10@gmail.com", e clicarmos em guardar, o comportamento deve ser o mesmo. Ou seja, ao clicar, deve aparecer o pop-up, o alerta aqui em cima, dizendo "registro realizado" e o e-mail que inserimos. Funcionou perfeitamente.

Então, qual é o ponto? Em que devemos nos atentar ao trabalhar com formulários? Aí vem a questão, a chave. Para que funcione bem com formulários, há uma peculiaridade que não existe quando não usamos formulários, como fizemos na última aula. A questão é que, quando colocamos um ngModel dentro de um input que está dentro de um formulário, precisamos ter essa propriedade, esse atributo chamado name.

No nosso input da linha 67 do arquivo details.component.html, temos um atributo name definido. Nosso formulário só continua funcionando porque já tínhamos esse name atribuído. Se removermos esse name, será que funciona? Vamos testar. O único ajuste que fiz foi esse: no input, removi o name. Vamos testar, escrevemos algo? Vou escrever "arielpaixão10.com". E se tentar enviar... Ops! Que estranho. Escrevi "arielpaixão10", mas aqui em cima apareceu "teste". Ou seja, meu ngModel se quebrou. Ele simplesmente não se comunica mais. Aqui vemos um exemplo claro.

<input id="newsletter-email" type="email" placeholder="Digite seu e-mail" [(ngModel)]="email" />

Corrigindo o problema e reiterando a necessidade do FormsModule

No HTML, qual é o valor que está no campo? arielpaixão10.com. E qual é o valor que está no TypeScript? teste.com. Esse foi o valor que definimos no arquivo TypeScript como valor padrão. Então, aqui no DTUseComponente.ts, linha 18, definimos o valor padrão da nossa propriedade email, que era "teste". Quando removemos isso, ao converter nosso campo de um div para um formulário e ao retirar a propriedade name, deixou de funcionar.

Aqui está o aviso: sempre que formos usar ngModel dentro de um formulário, é justamente o caso que temos agora. Observem. Estamos usando o ngModel no campo, na etiqueta input, e essa etiqueta input está dentro de um formulário. Gosto de fazer os quadros aqui para que fique bem claro visualmente. Quando fazemos isso, precisamos ter uma propriedade, um atributo chamado name. E aqui vamos descrever, colocar o nome deste campo, do valor que estamos introduzindo. Agora, apenas para que não fique igual ao newsletter email, vamos colocar o contrário, colocaremos email newsletter. Perfeito? Observem. Apenas por colocar este elemento aqui, volta a funcionar. Podemos ver que, ao carregar a tela, já aparece "teste@email", que foi definido por padrão. E se o alterarmos aqui e enviarmos, vejam, o valor está lá. Excelente. Voltou a funcionar perfeitamente.

<input id="newsletter-email" name="email-newsletter" type="email" placeholder="Digite seu e-mail" [(ngModel)]="email" />

Importância do FormsModule e conclusão

Agora, outro ponto para que não passe despercebido. Já sabemos que, ao trabalhar com formulários, sempre precisamos, ao usar ngModel, também usar o atributo name. Precisamos adicioná-lo, porque se não o fizermos, ele não reconhece e deixa de funcionar. O ngModel não entende que estamos fazendo as conexões entre arquivos e simplesmente deixa de funcionar. E só para reiterar, e para que não esqueçamos da primeira aula, é necessário que, ao usar ngModel, importemos o módulo chamado FormsModule no arquivo TypeScript. Então, aqui em Details, Componentes, TypeScript, é necessário importar este módulo, chamado FormsModule. Por quê? O ngModel, nosso two-way binding (vinculação bidirecional), não é padrão do HTML. É próprio do Angular. Então, precisamos importar esse elemento para avisar ao nosso HTML. Observem. No HTML, vamos utilizar uma propriedade que talvez não conheçam, mas fiquem tranquilos, é do Angular; o Angular a reconhece. É como se estivéssemos dizendo isso ao nosso projeto. Tanto que, se formos ao nosso Details, Componentes, TypeScript, linha 11, e eliminarmos a importação do FormsModule, e voltarmos ao HTML, vejam, começa a marcar um erro aqui. Aparece um sublinhado exatamente abaixo do ngModel que temos. E a própria aplicação, se voltarmos ao nosso sistema, já não funciona mais. Inclusive, mostra aqui: não conseguimos fazer o binding do ngModel, porque não é uma propriedade do input, da etiqueta input do HTML.

import { FormsModule } from '@angular/forms';

Então, só para reiterar, primeiro, se formos trabalhar com ngModel, importamos o FormsModule aqui. Se formos trabalhar com ngModel dentro de um formulário, provavelmente já o teremos importado aqui, e isso é um requisito prévio. E o requisito prévio número dois é que tenhamos um name dentro do input. Excelente, pessoal, isso é o que temos para a aula de hoje, para mostrar como podemos manter tudo funcionando, seja sem formulário ou com formulário.

Sobre o curso Angular: templates com bindings, control flow e pipes

O curso Angular: templates com bindings, control flow e pipes possui 290 minutos de vídeos, em um total de 56 atividades. Gostou? Conheça nossos outros cursos de Angular em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Angular acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas