APIs e Microsserviços

14 jul, 2017

Consumindo JSON via HTTP no Angular 4

Publicidade

Hoje, falaremos sobre como consumir um serviço que retorne um JSON, através de HTTP, utilizando o Service do Angular 4.

Para esse artigo, terei como premissa que você já tenha conhecimento sobre a instalação e configuração do Angular, NPM, Node.js etc., caso contrário, veja como fazer neste link.

Em nosso exemplo, faremos uma tela que o usuário digitará seu CEP e nossa aplicação irá consultar via serviço o frete a ser cobrado.

Como o intuito aqui é apresentar o uso de Service do Angular, o retorno JSON será um arquivo fake. A criação de uma API real ficará para um próximo artigo.

O primeiro passo é criar nossa aplicação através do Angular CLI, navegando até a pasta onde ficará seu projeto e digitando o comando a seguir:

ng new app-tutorial-json

Isso fará com que nosso ambiente seja criado na pasta indicada.

Ambiente criado, podemos dar inicio ao nosso exemplo. Primeiramente, irei abrir nosso editor, o Visual Studio Code, e abrir o nosso projeto criado na etapa anterior, conforme mostra a próxima figura.

Para visualizar o que já foi criado no nosso ambiente automaticamente, vamos iniciar nosso servidor através da linha de comando.

Abra novamente o prompt, navegue até a pasta do projeto e digite: ng serve

Se tudo ocorrer corretamente, você verá a tela conforme a imagem anterior. Note que ele indica a porta em que o servidor subiu, no caso, 4200; então, vá em seu browser e digite http://localhost:4200/. Você terá a aplicação rodando.

Nota: enquanto seu servidor estiver rodando, todas as alterações que fizer no código serão aplicadas imediatamente no browser, sem a necessidade de atualizar a página.

Em nosso exemplo, iremos utilizar o Bootstrap para facilitar o lado de estilização do app, portanto, insira a linha de código a seguir no header do arquivo Index.html, na raiz da aplicação:

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

Vamos agora remover esse código criado e aplicar o nosso, então, o primeiro passo é apagar o conteúdo do arquivo app.component.html e substituir pelo código seguinte:

<div class="container">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h1>Consultar Frete</h1>
    </div>

     <div class="panel-body">
        <div class="col-lg-12">
          <div class="col-lg-3 form-group">
            <div class="col-lg-12 form-group">
              <label>Digite seu CEP</label>
              <input id="Cep" type="text" size="9" maxlength="9" class="form-control"/>
            </div>

            <div class="col-lg-12 form-group">
              <input id="btnFrete" value="calcular Frete" class="btn btn-primary form-control" type="submit" (click)='CalcularFrete()' />   
            </div>

            <div class="col-lg-12 form-group">
              <a href="http://www.buscacep.correios.com.br/servicos/dnec/index.do" title="Não sei meu CEP" target="_blank" class="link">Não sei meu CEP</a>                     
            </div>                                    
          </div>

          <div class="col-lg-5">
              <div class="col-lg-6">            
                  <div *ngIf="frete">
                      <p><strong>Entrega Normal</strong></p>
                      <p>Em até {{frete.PrazoEntrega}} dias úteis</p>
                  </div>
              </div>
          </div>

          <div class="col-lg-4 text-center">
              <div *ngIf="frete">
                  <strong> Subtotal Frete R$ {{frete.ValorFrete}} </strong>
              </div>
              <div *ngIf="!frete">
                  <strong> Subtotal Frete CEP não informado</strong>
              </div>
          </div>
      </div>
     </div>

     <div class="panel-footer">
        <p>Sistema para Consulta de Frete</p>
     </div>

  </div>
</div>

Sua aplicação deverá estar com a seguinte aparência:

Pronto! Nosso html está finalizado.

Alguns pontos de atenção em nosso html:

  • O evento onClick no botão:
(click)='CalcularFrete()'

Ele será responsável por efetuar a chamada ao método que irá chamar nosso serviço.

  • A diretiva *ngIf, que é usada em alguns pontos para não gerar erro em caso de o objeto ser null.
div *ngIf="frete">

[(ngModel)]='cep'

Aqui estamos dizendo que esse campo é do tipo two-way-bind, ou seja, se alterarmos o valor dele no formulário, será alterado no componente também, e vice-versa.

Porém, para que essa diretiva funciona direito, precisaremos alterar nosso arquivo app.modules.rs. Faça o seguinte:

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

Adicione o import do modulo de Formulários no topo do arquivo:

imports: [
    BrowserModule,
    FormsModule
  ],

Import também na metadata.

Vamos, agora, criar nosso JSON Fake, que irá retornar o objeto Frete.

Crie uma pasta chamada API, embaixo da pasta src. Feito isso, crie um arquivo frete.json:

Cole nosso JSON:

"IdFreteEntregaTipo": 12,
    "Nome": "Frete",
    "ValorFrete": 15,    
    "PrazoEntrega": 3 
}

Html e JSON criados, vamos, então, construir nosso serviço, que será responsável por ir até nossa API fake e retornar o Frete.

Para mapear o objeto retornado em nosso serviço, precisamos criar nossa classe Frete, portanto, crie um arquivo na pasta src, chamado Frete.ts e insira o código abaixo para montar nosso objeto:

export class Frete{    
    public IdFreteEntregaTipo: number;
    public Nome: string;
    public ValorFrete: number;
    public PrazoEntrega: number
}

Dentro da pasta app, crie um arquivo e nomeie ele para app.service.ts. Dentro desse arquivo, teremos o seguinte código:

import { Injectable } from '@angular/core';
import { Frete } from './Frete';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/do';

@Injectable()
export class FreteService {
    private _Url = 'http://127.0.0.1:8887/frete.json';

    constructor(private _http: Http) { }
    
    getFrete(cep: string): Observable<Frete> {
        return this._http.get(this._Url)
            .map((response: Response) => <Frete>response.json())
            .do(data => console.log('All: ' + JSON.stringify(data)))
            .catch(this.handleError);
    }

    private handleError(error: Response) {
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }
}

Explicando ponto a ponto do método acima:

import { Frete } from './Frete';

Aqui, precisamos importar nossa classe que criamos no passo anterior, para poder utilizá-la dentro do serviço.

@Injectable()

Aqui indicamos o uso da injeção de dependência e, a partir de agora, para utilizar nosso serviço, precisamos apenas injetar uma instância em no construtor que irá consumir esse serviço.

private _Url = 'http://127.0.0.1:8887/frete.json';

Propriedade com a url da nossa API, no caso, nosso arquivo JSON.

Logo, explicarei como gerar essa url facilmente para ser acessada como um servidor.

constructor(private _http: Http) { }

Injetamos a classe de http, que utilizaremos para buscar os dados.

getFrete(cep: string): Observable<Frete> {
        return this._http.get(this._Url)
            .map((response: Response) => <Frete>response.json())
            .do(data => console.log('All: ' + JSON.stringify(data)))
            .catch(this.handleError);
    }

Esse é o nosso método que efetivamente irá consultar a API e retornar o frete.

Nota: O método possui como parâmetro o CEP a ser consultado, porém como nossa API é fake, não estamos fazendo nada com esse parâmetro.

O Observable serve para emitir uma notificação toda vez em que houver alteração em seu item, no caso, o frete.

Na sequência, fazemos a chamada via o método get da classe http e efetuamos o mapeamento, dizendo que a resposta obtida deve ser mapeada para o objeto do tipo FRETE.

private handleError(error: Response) {
        console.error(error);
        return Observable.throw(error.json().error || 'Server error');
    }

Por fim, caso algo dê errado, chamamos o método handleError.

Já temos nosso html e nossa API que retornará o JSON, nosso Objeto Frete e acabamos de implementar nosso serviço. Chegou a hora de consumir esse serviço e exibir na tela para o usuário. Vamos lá!

Abra o arquivo app.component.ts. Será onde iremos fazer a implementação.

Iniciaremos importando nosso serviço, nosso objeto e o observable:

import { Observable } from 'rxjs/Observable';
import { Frete } from 'app/Frete';
import { FreteService } from 'app/app.service';

No próximo passo, vamos começar criando uma propriedade chamada Frete, que será nosso frete retornado, e o construtor de nossa classe:

frete: Frete;        
    
    constructor(private _freteService: FreteService) {

    }

Aqui, em nosso construtor, injetamos nosso serviço, disponibilizando para uso em nosso componente na variável _freteService.

Feito isso, implementaremos nosso método de calcular o frete:

CalcularFrete(): void {
        this._freteService.getFrete(this.cep)
            .subscribe((data: Frete) => this.frete = data,
            error => console.log(error));
    }

Esse método é responsável por ir até nosso serviço, consultar a API e, então, preencher a nossa propriedade do tipo FRETE com o resultado obtido.

Ele faz isso através do operador Subscribe, que é o responsável por, a cada atualização do Observable, atualizar nosso objeto Frete.

Por fim, para finalizarmos e ver se nossa aplicação está rodando, precisamos registrar nosso serviço. Fazemos isso adicionando um provider em nosso modulo. Para isso, abra o arquivo app.module.ts e insira o nome do nosso serviço na metadata providers.

Note também que precisamos adicionar as referências para o módulo http.

Enfim, nossa aplicação está pronta.

Mas se você rodar, ela irá logar um erro no console, dizendo que não encontrou nosso JSON.

Para resolver isso, eu utilizei uma extensão do Chrome, chamada “Web Server for Chrome”, que transforma uma pasta local em um servidor web.

Aponte para a pasta que está nosso JSON, no caso a pasta API. Feito isso, vá em “Show Advanced Settings” e selecione a opção “Set CORS Headers”.

Pronto! Agora, sim, temos nossa aplicação de cálculo de frete finalizada.

E assim finalizamos nossa aplicação. Espero que tenham gostado, replicado com sucesso os códigos e, mais importante de tudo, entendido o conceito e o que cada trecho do sistema faz.

Caso você queira baixar o código fonte, acesse: https://github.com/brunohenz/tutorial-http-angular4

Abraços e bons estudos!