Angular

13 abr, 2020

Covid19 API com Angular 9

Publicidade

Estamos vivendo tempos difíceis com a epidemia do coronavírus. Assim, pode ser uma oportunidade para aprimorar habilidades e avançar nos estudos. #fiqueemcasa

A proposta deste artigo é construir uma aplicação Web em Angular 9 que consume dados da API COVID19.

Abaixo, como ficará a aplicação.

Se preferir, escrevi um tutorial dessa mesma API com Flutter. O tutorial e o código estão aqui.

Passos iniciais

Caso você seja iniciante no framework, recomendo o link para criação do projeto.

Após a construção, vamos importar o módulo no módulo principal da aplicação.

No arquivo , realize o import e a assinatura no array de imports:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule} from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Codificando as classes

Vamos criar o modelos que mapeia os dados relacionados as informações gerais da pandemia.

Dentro da pasta app, crie a pasta models e o arquivo .

export interface Mundo {
    cases : number;
    deaths : number;
    recovered : number;
    affectedCountries : number;
    updated : number;
}

Mapeamos as informações relacionadas aos números de infectados, mortes, quantidade de países afetados e a última atualização.

Vamos criar em seguida o model que representa os casos do país, já que a API traz informações específicas de cada lugar.

Na mesma pasta, crie o arquivo 

import { Mundo } from './mundo.model';

export interface Pais extends Mundo {
    country: string;
    todayDeaths: number;
    critical: number;
    casesPerOneMillion: number
    deathsPerOneMillion: number;
    countryInfo: CountryInfo;
}

interface CountryInfo {
    flag: string;
}

Utilizando um pouco de orientação a objetos, na assinatura da criação da interface herdamos a interface Mundo com extends, já que há campos em comum.

Declaramos os atributos específicos do país como o nome, número de mortos do dia, números de pessoas internadas em estado crítico, além de um objeto aninhado, , que retorna uma imagem da bandeira.

Criando o serviço

Vamos criar o serviço que acessa o endpoint da API e métodos.

No terminal, informe o comando:

ng g service services/covidapi

Vamos editar o arquivo  que se encontra na pasta services.

O código será:

import { Pais } from './../models/pais.model';
import { Mundo } from './../models/mundo.model';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class CovidapiService {

  url = 'https://corona.lmao.ninja/v2'

  constructor(private http: HttpClient) { }

  async getInfoMundo() {
    return await this.http.get<Mundo>(`${this.url}/all`)
    .toPromise()
    .then(mundo => {return mundo});
  }

  getInfoPais(pais: string = 'brazil') {
    return this.http.get<Pais>(`${this.url}/countries/${pais}`)
    .toPromise()
    .then(pais => {return pais})
  }

}

Definimos o endpoit da API no atributo url.

Fazemos a injeção de HttpClient no método construtor para requisitar chamadas na API. Em seguida, codificamos o método . Como o operador get, tipando o retorno com a interface criada <Mundo>, informando a url e concatenada com ‘/all’.

Dessa forma, as informações gerais do pandemia.

Na sequência, usamos o método e no callback retorno o objeto.

A promise é uma abstração para representar fluxos de ações em códigos assíncronos, processando um único evento quando uma operação assíncrona é concluída ou falha.

Nesse outro artigo aqui, eu invoco também uma api, mas usando Observables.

No método , escrevo um parâmetro e defino um valor padrão brasil, caso nenhum seja informado. A diferença está na chamada da requisição, concatenando com a string ‘/countries/${pais}’, para acessar informações específicas do país informado.

Componente e View principal

Vamos editar o componente principal, mas antes instalaremos a biblioteca sweetalert2.

No terminal informe:

npm install sweetalert2.

Abra o arquivo  e codifique assim:

import { Pais } from './models/pais.model';
import { Mundo } from './models/mundo.model';
import { CovidapiService } from './services/covidapi.service';
import { Component, OnInit } from '@angular/core';
import Swal from 'sweetalert2';

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

  mundo: Mundo;
  pais: Pais;

  constructor(private apiService: CovidapiService) {}

   async ngOnInit(){  
   this.mundo = await this.apiService.getInfoMundo();
   this.pais = await this.apiService.getInfoPais();   
  }

  async trocaPais(){
    const { value: inputPais } = await Swal.fire({
      title: 'Informe um País:',
      input: 'text',
      inputPlaceholder: 'País'
    })
    if (inputPais) {
      this.pais = await this.apiService.getInfoPais(inputPais)
    }
  }
    
}

Declaramos as interfaces mundo e pais e no construtor, realizamos a injeção de dependência do serviço codificado no passo anterior.

No método , chamamos os métodos com o operador await bindando as interfaces no carregamento inicial no componente.

Finalmente o método trocaPais, apresenta um dialog com um input. Se existir valor, passamos no parâmetro do método 

Não esqueça de apagar todo o conteúdo existente em , gerado na construção do projeto.

Abaixo, um trecho inicial do código. O código do template, assim como do projeto está disponível no meu Github, no final do artigo.

<div class="container py-3">

  <div ngIf="mundo">
    <div class="row table-dark m-2 round text-center">
      <h2 class="text-white mx-auto ">COVID-19 </h2>
      <h3 class="text-white mx-auto"> Informações Gerais </h3>
      <p class="mx-auto"> Atualizado em {{(mundo.updated | date : 'dd/MM/yy HH:mm')}} </p>
    </div>

    <!-- Formacoes Gerais-->
    <div class="row ">
      <div class="col-md-12">
        <div class="card-counter info">
          <i class="fa fa-users fa-3x"></i>
          <span class="count-numbers">{{mundo.cases}}</span>
          <span class="count-name">TOTAL DE CASOS MUNDO</span>
        </div>
      </div>

Para prevenir-se de erros de renderização, utilizamos uma diretiva estrutural  para verificar a existência do objeto.

No campo da atualização, eu informo um Pipe para transformar em data, especificando um formato ‘dd/MM/yy HH:mm’.

Se tiver alguma dúvida, deixe no comentários.

Se cuidem, e que Deus nos proteja.

Veja aqui o link do repositório