Olá! Boas-vindas a mais um curso de Angular! Eu sou Vinicios Neves e vou te acompanhar nessa jornada.
Vinícios Neves é um homem de pele clara com rosto oval. Tem olhos castanho-escuros, sobrancelhas grossas, nariz comprido e boca larga. No rosto, tem barba e bigode, além de um óculos de grau com armação quadrada preta. No corpo, uma camiseta cinza. Está sentado em uma cadeira cinza. Ao fundo, uma parede lisa com iluminação em degradê nas cores azul e rosa.
Vamos evoluir o projeto Jornada Milhas. No curso anterior apresentado pela instrutora Nay e eu, implementamos a camada visual com a ajuda do Figma. Recomendamos que ele seja assistido antes deste, contudo, se não houver interesse, disponibilizaremos esse projeto base finalizado.
Com a camada visual implementada, focaremos em desenvolver o comportamento do formulário de busca.
Observando-o superficialmente, parece uma tarefa simples. Contudo, precisaremos compartilhar o estado entre as partes do formulário armazenadas em modais e em outros componentes. Para chegar a esse resultado, experimentaremos diversas situações diferentes, nas quais traçaremos estratégias para atingir nossos objetivos.
Além disso, subiremos o back-end e trabalharemos com requisições, buscando estados brasileiros, promoções e depoimentos.
Se você:
Te convidamos a embarcar conosco no Jornada Milhas mais uma vez e desenvolver toda a aplicação, tornando-a pronta para os próximos passos. Este é só mais um pedaço do que implementaremos nessa aplicação.
Te esperamos no primeiro vídeo!
Para evoluir o Jornada Milhas, nos preocuparemos em criar a camada de comunicação que obterá dados de promoções da API (a fonte de verdade).
Após clonar o projeto do curso anterior em uma pasta denominada "jornada-milhas" e alocar a API em uma pasta denominada "api-jornada-milhas", vamos abrir o terminal, por meio do qual acessaremos a pasta da API com o comando abaixo.
cd api-jornada-milhas
Em seu interior, rodaremos o comando abaixo para garantir que tudo está atualizado.
npm i
Para subir a API, rodaremos o comando abaixo.
npm run start:dev
Como resultado, a API ficará disponível na porta 8080. Vamos abrir uma nova guia do navegador e digitar o caminho abaixo para acessá-la.
localhost:8080/api
Em seu interior, veremos o título "Jornada Milhas 1.0" e uma lista de métodos disponíveis. Inicialmente, vamos focar no método que buscará promoções.
GET/promocoes
Essa documentação é o Swagger e nos permite experimentar a execução deste método para verificar seu funcionamento. Vamos clicar nele para abrir uma seção abaixo dele, no interior da qual buscaremos o botão "Try it out" (Testar) no canto superior direito.
Após o clique neste botão, será exibido abaixo dele um botão denominado "Execute" (Executar), ocupando toda a largura da tela. Após clicarmos nele, dentro do Swagger ocorrerá uma divisão que o transformará em dois botões: "Execute" à esquerda e "Clear" (Limpar)" à direita.
Abaixo de ambos, serão exibidas três seções: a primeira delas, intitulada "Curl" é a superior, dentro da qual veremos que ele executou uma requisição do tipo GET
em localhost:8080/promocoes
.
curl -X 'GET' \
'http://localhost:8080/promocoes' \
-H 'accept: application/json'
A seção do meio se chama "Request URL" (URL da requisição) e possui a URL utilizada.
http://localhost:8080/promocoes
Já a maior seção, abaixo da segunda, denomina-se "Server Response" (Resposta do Servidor). Nela, temos duas colunas: à esquerda, a coluna "Code" com o código de status "200"; à direita, "Details" (Detalhes), que possui o bloco intitulado "Response body" (Corpo da resposta). Este último trouxe a estrutura da promoção, constituída de um ID, um destino, a URL de uma imagem e o preço.
[
{
"id": 11,
"destino": "Atacama",
"imagem": "http://localhost:8080/public/atacama.png",
"preco": 2500
},
{
"id": 12,
"destino": "Veneza",
"imagem": "http://localhost:8080/public/veneza.png",
"preco": 1500
},
{
"id": 13,
"destino": "Patagônia",
"imagem": "http://localhost:8080/public/patagonia.png",
"preco": 750
},
*Trecho do retorno omitido*
]
Vamos conectar o Jornada Milhas nesse back-end. Para isso, voltaremos ao terminal, no qual abriremos uma nova aba. Nesta, voltaremos ao Desktop com o comando abaixo.
cd ..
Listaremos as pastas com o comando abaixo.
ll
Nos resultados, veremos as pastas "api-jornada-milhas" e "jornada-milhas".
drwxr-xr-x 21 vinny staff 672B Jun 28 20:39 api-jornada-milhas
drwxr-xr-x 15 vinny staff 480B Jun 28 20:28 jornada-milhas
Entraremos na pasta do curso anterior por meio de um cd
nela.
cd jornada-milhas
Rodaremos o comando abaixo para instalar todas as dependências desse projeto.
npm i
Observação: O
npm i
constitui o atalho para o comandonpm install
.
Após a instalação dos pacotes, faremos um ng serve
para subir o ambiente de desenvolvimento do Angular.
ng serve
Enquanto isso, abriremos uma terceira aba no terminal, onde solicitaremos a execução do VS Code a partir da pasta "jornada-milhas".
code .
Neste momento, temos a janela do VS Code, o terminal, cuja segunda aba está executando o Angular na porta 4200 e a primeira aba está executando a API. Temos que manter ambos rodando.
Voltando ao navegador, abriremos uma nova guia na qual acessaremos a URL abaixo
localhost:4200
Essa URL carregará a página inicial do Jornada Milhas, na qual temos modais ativados pelos filtros de categorias — por exemplo, na seção "Passagens", temos dois botões para as categorias "1 adulto" e "Econômica", respectivamente. Clicando em uma delas, um modal intitulado "Viajante" será exibido, onde temos a opção de selecionar e buscar uma dessas categorias.
Na mesma seção, abaixo dos botões, temos campos de busca e de data para configurar nossas viagens. Podemos ver que nosso projeto base funciona, contudo, ele é estático.
Se descermos a tela para a seção "Promoções" veremos vários cartões iguais, representando uma viagem para Veneza por R$ 500,00. Vamos mudar isso e trazer dinamismo para o projeto.
Voltando à guia do navegador com a página do Swagger aberta na porta 8080, veremos o retorno que já abordamos e que contém a estrutura de uma promoção — ou seja, nossa interface. Ela possui:
A partir dessas informações, voltaremos ao VS Code e acessaremos o explorador lateral, no qual percorreremos o caminho de pastas "src > app" e criaremos dentro desta última a pasta "core". Em seu interior, alocaremos tudo o que for global na aplicação.
Dentro de "core", criaremos outra pasta denominada "types", em cujo interior criaremos o arquivo types.ts
, que alocará todas as interfaces.
Dica: Também é possível separar cada interface em um arquivo. Fica a critério de cada dev.
No interior do arquivo types.ts
, criaremos uma interface de Promocao
, exportando-a ao mesmo tempo, com o comando export interface Promocao
. À sua direita, abriremos um bloco de chaves, dentro do qual receberá os atributos vistos:
id: number
destino: string
imagem: string
preco: number
export interface Promocao {
id: number
destino: string
imagem: string
preco: number
}
Com a forma da interface de Promocao
criada, podemos pedir ao Angular que gere um serviço para realizar a camada de comunicação entre nossa aplicação e o back-end.
Voltando ao terminal, temos a terceira aba com acesso à pasta "jornada-milhas", parada e disponível. Dentro dessa pasta, pediremos para que o angular (ng
) gere um serviço (g s
).
Vamos solicitar que seja criada a pasta "services" (serviços) e o arquivo promocao
dentro da pasta "core", por meio do comando core/services/promocao
.
ng g s core/servicos/promocao
Pressionaremos "Enter" para rodar o comando acima. O terminal nos avisará que a geração foi efetuada, mas conferiremos no VS Code.
Por meio do explorador, expandiremos o caminho de pastas "app > core > services" e veremos dois arquivos:
promocao.service.spec.ts
, referente aos testes;promocao.service.ts
, referente ao serviço em si.No interior do arquivo de serviço, veremos que ele foi criado como Injectable
— ou seja, podemos injetá-lo em nossas classes do Angular. Além disso, ele provém do root
— isso significa que só haverá uma instância deste serviço para a aplicação inteira.
O nome deste padrão de projetos é Singleton — caso queira mergulhar neste assunto, disponibilizaremos nessa aula uma atividade sobre ele.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class PromocaoService {
constructor() { }
}
Com a base pronta e os serviços gerados, configuraremos a camada HTTP necessária para se comunicar com o back-end. Faremos isso a seguir.
O Angular, similar a um canivete suíço com mil e uma utilidades, nos entrega a camada que abstrai as requisições HTTP necessárias para que o Jornada Milhas funcione integrado ao back-end.
Acessaremos o VS Code e, no interior do arquivo promocao-service.ts
, injetaremos o nosso HttpClient
entre os parênteses do constructor()
. Vamos pressionar "Enter" neste local e adicionar o nível de acesso private
junto a um httpClient
com "h" minúsculo.
Vamos tipá-lo como HttpClient
com "h" maiúsculo para que o Angular saiba o que queremos injetar aqui.
@Injectable({
providedIn: 'root'
})
export class PromocaoService {
constructor(
private httpClient: HttpClient
) { }
}
Ao digitar "HttpClient", o VS Code abrirá uma lista de sugestões, entre as quais há a importação do HttpClient
proveniente da rota "@angular/common/http".
Vamos selecioná-la, permitindo que seja importada no início do arquivo atual por meio do comando abaixo.
import { HttpClient } from '@angular/common/http';
Vamos salvar o código e voltar ao navegador, onde verificaremos a aba da aplicação na porta 4200 em busca do resultado.
Vamos recarregar a página e abrir a aba do inspecionador de elementos por meio do botão direito e da opção "Inspecionar Elemento". Acessaremos esse inspecionador na aba lateral direita, selecionando a guia do console e verificando que não há erros apontados.
Com isso, temos nosso HttpClient disponível para uso. Voltaremos ao VS Code e seguiremos para a próxima etapa.
No mesmo arquivo promocao-service.ts
, abaixo do HttpClient
, adicionaremos um método. Considerando que se trata de um serviço que trata exclusivamente de promoções, listando as disponíveis, podemos chamar esse método de listar()
.
@Injectable({
providedIn: 'root'
})
export class PromocaoService {
constructor(
private httpClient: HttpClient
) { }
listar() {
}
}
Vamos tipá-lo, pedindo que retorne um Observable
. Ao digitar "Observable", o VS Code abrirá uma lista de sugestões, entre as quais há a importação do Observable
proveniente de "rxjs".
Vamos selecioná-la, permitindo que seja importada no início do arquivo atual por meio do comando abaixo.
import { Observable } from 'rxjs';
Esse Observable
, no qual adicionaremos o Generics do TypeScript por meio dos sinais de menor e maior para dizer em seu interior que ele trabalha com Promocao
. Este último é o type
, ou seja, a interface que acabamos de criar.
O Promocao
é um arranjo com uma lista de promoções, portanto, adicionaremos um par de colchetes à sua direita.
@Injectable({
providedIn: 'root'
})
export class PromocaoService {
constructor(
private httpClient: HttpClient
) { }
listar() : Observable<Promocao[]>{
}
}
No interior das chaves de listar
, adicionaremos um this.httpClient.get<Promocao>()
que retornará um arranjo de promoção, por isso utilizaremos o Generics. À esquerda desta linha, adicionaremos um return
.
Entre os parênteses, adicionaremos aspas simples, entre as quais informaremos a URL na qual a requisição será efetuada.
@Injectable({
providedIn: 'root'
})
export class PromocaoService {
constructor(
private httpClient: HttpClient
) { }
listar() : Observable<Promocao[]>{
return this.httpClient.get<Promocao>('')
}
}
Quando falamos em URL, temos a API rodando no navegador em "localhost:8080". No ambiente de desenvolvimento, esta é a URL utilizada.
Quando publicarmos a aplicação, é provável que o endereço mude. Pensando nisso, qualquer aplicação robusta, inclusive o Angular, entrega uma forma para lidar com essas variáveis de ambiente.
No navegador, voltaremos à guia aberta com a documentação do Angular, onde buscaremos a seção "Configuring application environments" (Configurando ambientes da aplicação).
Nela, o primeiro comando é solicitar ao ng
que gere os ambientes.
ng generate environments
Vamos copiar esse código e voltar à terceira aba do terminal, que está disponível. Lembrando que temos outras duas abas rodando o front-end (Angular) e o back-end. Ambas não podem ser fechadas.
Vamos colar o código na aba disponível e pressionar "Enter". No retorno, o terminal dirá que o arquivo angular.json
foi criado e atualizado.
UPDATE angular.json (3283 bytes)
Vamos voltar ao VS Code, rolar a aba do explorador para baixo e localizar a pasta "environments", dentro da qual encontraremos dois arquivos: environment.development.ts
(o ambiente de desenvolvimento) e environment.ts
(o ambiente produtivo).
Dentro de environment.development.ts
, temos um bloco de chaves do export const environment
. Entre as chaves, criaremos a apiUrl
que receberá a string do endereço base da API. Vamos recolhê-la no Swagger.
Voltando ao navegador, na aba do Swagger, veremos o endereço "localhost:8080/api#/default/PromocoesController_findAll". Ou seja, usaremos a porta 8080.
A API mencionada nesse endereço se refere ao endereço da documentação do Swagger. Dentro da página em si, temos a seção "Request URL", onde veremos o exemplo com o endereço a ser utilizado: "http://localhost:8080/promocoes".
A partir do endereço de exemplo, copiaremos somente a base.
http://localhost:8080
Voltando ao VS Code, colaremos o conteúdo copiado entre as aspas simples de apiUrl
, dentro do ambiente de desenvolvimento.
export const environment = {
apiUrl = 'http://localhost:8080'
}
Por meio do explorador, acessaremos o arquivo environment.ts
, referente ao ambiente produtivo. Entre as chaves de export const environment
, adicionaremos a mesma apiUrl
que receberá entre aspas simples a URL final — que, neste caso, será http://api.jornadamilhas.com
.
Essa URL não existirá, por enquanto. Contudo, servirá para alcançar o objetivo de alinhar os arquivos, criando uma entrada de produção correspondente a cada entrada de desenvolvimento.
export const environment = {
apiUrl = 'http://api.jornadamilhas.com'
}
Após criar os ambientes, temos que "derrubar" o Angular e subi-lo novamente, permitindo que ele saiba lidar com os novos elementos. Para isso, acessaremos a segunda aba do terminal, na qual pressionaremos "Ctrl+C" para parar a execução.
Vamos limpar esse terminal e rodar em seguida o ng serve
para servir a aplicação.
ng serve
Durante este momento, ele sobrescreverá automaticamente o environment
com o environment.development
, permitindo o acesso à API http://localhost:8080
que funcionará somente em nossa máquina.
Com o acesso disponível, voltaremos ao serviço promocao.service.ts
, onde criaremos um atributo private
chamado apiUrl
tipado como string
. Ele será adicionado na primeira linha entre as chaves do export class PromocaoServico
.
Vamos importar o arquivo environment
. Para que o Angular funcione, sempre devemos importar este, e não o environment.development
, portanto, selecionaremos na lista de sugestões do editor a opção "environment" proveniente do caminho "src/environments/environment".
Importação automática do VS Code:
import { environment } from 'src/environments/environment';
Se adicionarmos um ponto à direita de environment
, o editor sugere apiUrl
. Vamos selecioná-lo.
Código da classe atual:
@Injectable({
providedIn: 'root'
})
export class PromocaoService {
private apiUrl: string = environment.apiUrl;
constructor(
private httpClient: HttpClient
) { }
listar() : Observable<Promocao[]>{
return this.httpClient.get<Promocao>('')
}
}
Por último, entre os parênteses de this.httpClient.get<Promocao>('')
, retiraremos as aspas simples e adicionaremos um this.apiUrl
e concatenaremos o /promocao
. Para isso, adicionaremos crases e chaves ao redor de this.apiUrl
. À esquerda da chave de abertura, adicionaremos um dólar ($
).
Com isso, a string será interpolada. À direita da chave de fechamento, adicionaremos o restante da URL: /promocoes
.
@Injectable({
providedIn: 'root'
})
export class PromocaoService {
private apiUrl: string = environment.apiUrl;
constructor(
private httpClient: HttpClient
) { }
listar() : Observable<Promocao[]>{
return this.httpClient.get<Promocao>(`${this.apiUrl}/promocoes`)
}
}
Com essa configuração, temos uma forma de realizar a requisição HTTP. Tudo pronto para testarmos.
Por meio do explorador, buscaremos a pasta "pages", dentro da qual acessaremos o arquivo home.component.ts
.
Em seu interior, entre as chaves de export class HomeComponent
, criaremos um constructor()
acompanhado de um bloco de chaves. Entre seus parênteses, configuraremos o modificador de acesso private
denominado servicoPromocao
que receberá o tipo PromocaoService
.
export class HomeComponent {
constructor(private servico Promocao: PromocaoService) {
}
}
Ao digitar o tipo, o editor sugerirá a importação de PromocaoService
proveniente de "src/app/core/services/promocao.service". Vamos selecioná-la, permitindo a importação automática dela através do comando abaixo.
import PromocaoService } from 'src/app/core/services/promocao.service';
À direita de HomeComponent
, faremos um implements OnInit
. Com isso, a classe HomeComponent
será sublinhada em vermelho, apresentando um erro. Se posicionarmos o cursor em cima dele, o editor exibirá um diálogo avisando que, para implementar o OnInit
, essa classe deve implementar o método ngOnInit
.
Para implementá-lo, clicaremos no ícone de lâmpada azul, localizada acima da linha atual, no canto esquerdo. Ele abrirá uma caixa de sugestão, na qual selecionaremos "Implement interface 'OnInit'" (Implementar interface 'OnInit').
Após o clique, o VS Code construirá o método ngOninit()
abaixo do construtor.
export class HomeComponent {
constructor(private servico Promocao: PromocaoService) {
}
ngOnInit(): void {
throw new Error('Method not implemented.');
}
}
Ele não fará um throw new Error
, por isso, deletaremos essa linha e a substituiremos por um this.servicoPromocao.listar()
.
export class HomeComponent {
constructor(private servico Promocao: PromocaoService) {
}
ngOnInit(): void {
this.servicoPromocao.listar();
}
}
Vamos verificar no navegador se essa requisição será feita. Na aba da aplicação Jornada Milhas, recarregaremos a página e veremos um erro de muitas linhas na aba lateral do console, indicando que não há um provedor HttpClient e consequentemente o Angular não consegue realizar a entrega.
ERROR Error: Uncaught (in promise):
NullInjectorError: R3InjectorError (AppModule) [PromocaoService -> HttpClient-> HttpClient]:
NullInjectorError: No provider for HttpClient!
Retorno omitido
Isso ocorreu porque não configuramos o módulo HTTP.
Voltando ao VS Code, no explorador, acessaremos o arquivo app.module.ts
dentro do caminho de pastas "src > app". Em seu interior, buscaremos o arranjo de imports
, dentro do qual adicionaremos como último elemento um HttpClientModule
.
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatToolbarModule,
MatButtonModule,
MatCardModule,
MatButtonToggleModule,
MatIconModule,
MatChipsModule,
MatFormFieldModule,
MatInputModule,
MatDatepickerModule,
MatNativeDateModule,
MatDialogModule,
HttpClientModule
]
Voltando ao navegador, veremos que o erro não aparece mais no console. Vamos recarregar a página e constatar que tudo funciona bem.
À direita da aba "Console", clicaremos na aba "Network", recarregaremos a página e veremos que a requisição não será feita.
Temos o serviço funcionando, realizamos as injeções, mas não conseguimos verificar a execução da requisição nem visualizar os dados. As seguir, veremos como resolver esse problema.
O curso Angular: componentização, formulários e interação com APIs possui 107 minutos de vídeos, em um total de 44 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:
Impulsione a sua carreira com os melhores cursos e faça parte da maior comunidade tech.
1 ano de Alura
Assine o PLUS e garanta:
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
No Discord, você tem acesso a eventos exclusivos, grupos de estudos e mentorias com especialistas de diferentes áreas.
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
Acelere o seu aprendizado com a IA da Alura e prepare-se para o mercado internacional.
1 ano de Alura
Todos os benefícios do PLUS e mais vantagens exclusivas:
Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos, corrige exercícios e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com a Luri até 100 mensagens por semana.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Transforme a sua jornada com benefícios exclusivos e evolua ainda mais na sua carreira.
1 ano de Alura
Todos os benefícios do PRO e mais vantagens exclusivas:
Mensagens ilimitadas para estudar com a Luri, a IA da Alura, disponível 24hs para tirar suas dúvidas, dar exemplos práticos, corrigir exercícios e impulsionar seus estudos.
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Escolha os ebooks da Casa do Código, a editora da Alura, que apoiarão a sua jornada de aprendizado para sempre.