Criando tela de consulta via API com Angular e PO UI

Agora que temos uma API para consultar cidades cadastradas no sistema como demonstrado no artigo anterior.

Criando consulta customizada desde o back-end via API até o front-end com Angular e POUI

Vamos criar uma tela de consulta para que possamos visualizar esses dados.

Vamos seguir o guia de primeiros passos do PO UI nesta pagina: https://po-ui.io/guides/getting-started

No final do artigo listarei uma lista de referencias usadas para estudo deste desenvolvimento.

Iniciando o projeto

Com o comando abaixo vamos criar um projeto em Angular chamado cstCidades

ng new cstCidades

Quando questionado se desejava criar rotas informei que sim digitando Y e quanto ao stylesheet selecionei a opção CSS:

após seguir o passo a passo do guia fornecido pelo getting-started e usar pela primeira vez o comando “ng serve -o” para que o projeto seja executado e aberto no navegador padrão quando estiver pronto:

Até este momento eu estava me baseando na seguinte postagem no Medium más ela é referente ao THF ainda, versão anterior ao PO.UI.

Acabei de localizar uma postagem mais recente no Blog sempreju que pode auxiliar melhor na elaboração do conteúdo, por isso se quiser ver o conteúdo original dá uma passada lá.

Dando continuidade ao projeto

Neste momento vamos criar três módulos responsaveis por buscar os dados e apresentar em tela para o usuário, vamos usar os seguintes comandos:

ng generate module cst-cidades
ng generate service cst-cidades\cst-cidades
ng generate component cst-cidades

Com isso temos o seguinte resultado:

Primeiramente iremos configurar o serviço responsável por coletar os dados em nossa API, vamos editar o cst-cidades.service.ts, deve ficar parecido com o seguinte código:

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { PoTableColumn } from '@po-ui/ng-components';
import { Observable } from 'rxjs';
import { Subscription } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class CstCidadesService {
  //Endereço da nossa API responsável por lista
  ApiRest = 'http://servidor:porta/dts/datasul-rest/resources/prg/dms/v1/api_cidades';
   
  constructor(private http: HttpClient) { }

  httpOptions = {
    headers: new HttpHeaders({
      'Content-Type':  'application/json;charset=UTF-8',
      'Authorization': 'Basic ' + btoa('usuario:senha'),
    })
  };

  //Método responsável por buscar e listar registros
  getCidadesList(): Observable<any> {
    return this.http.get(this.ApiRest , this.httpOptions);
  }

  //Método para editarmos o nome das colunas de forma mais apresentavel
  // por exemplo cdnMunpioIbge que apresentamos como Cód.IBGE, mais amigavel ao usuario
  getColumns(): Array<PoTableColumn> {
    return [
      { property: 'cidade', label: 'Cidade'},
      { property: 'estado', label: 'Estado' },
      { property: 'sigla', label: 'sigla' },
      { property: 'cdnMunpioIbge', label: 'Cód.IBGE' },
      { property: 'pais', label: 'País' },
    ];
  }
}

Repare que no código acima estamos usando um Basic authentication para consumir a API, use um usuário e senha válidos que estejam cadastrados no ERP.

Agora que o serviço responsável por coletar os dados via API está configurado vamos preparar o Back-end da tela de consulta, vamos configurar o componente cst-cidades.component.ts para apresentar os dados a interface, se baseie no seguinte código:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { PoNotificationService } from '@po-ui/ng-components';
import { CstCidadesService } from './cst-cidades.service';

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

  cidadesList: Array<any> = new Array();
  colunasTable: Array<any> = new Array();
 
  constructor(private CstCidadesService: CstCidadesService,
    private router: Router,
    private poNotification: PoNotificationService) { }
 
  ngOnInit(): void {
    this.updateCidadesList(); //busca a lista em nosso Api
    this.colunasTable = this.CstCidadesService.getColumns(); //atualiza o titulo das colunas
  }
  //Metódo responsável por se isncrever no serviço e atualizar a lista de fornecedores
  updateCidadesList(): void {
    this.CstCidadesService.getCidadesList().subscribe(response => {
      this.cidadesList = response.items;
    });
  }

}

Agora podemos configurar o HTML para apresentar o resultado da consulta em tela para o suario, vamos usar o seguinte código:

<po-page-default p-title="Lista de Fornecedores">
    <po-table
      p-container="light"
      [p-columns]="colunasTable"
      [p-items]="cidadesList">
    </po-table>
  </po-page-default>

Antes de executar e conferir o resultado precisamos configurar a rota para acessar a nova tela criada, para isso vamos modificar o app-routing.modules.ts da seguinte forma:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CstCidadesComponent } from './cst-cidades/cst-cidades.component';
 
const routes: Routes = [
  { path: '', component: CstCidadesComponent },
  { path: 'cidades', component: CstCidadesComponent }, //lista de cidades
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Devemos ainda alterar o conteúdo do app.component.html, vamos trocar o conteúdo padrão pelo código que redireciona conforme a rota que acabamos de configurar:

<div class="container">
  <router-outlet></router-outlet>
</div>

Agora devemos configurar o app.module.ts onde vamos importar todos os módulos que criamos e nos referenciamos no projeto, o código dele deve ficar parecido com isso:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PoModule } from '@po-ui/ng-components';
import { RouterModule } from '@angular/router';
import { PoNotificationModule  } from '@po-ui/ng-components';
import { PoDynamicModule } from '@po-ui/ng-components';
import { PoButtonModule } from '@po-ui/ng-components';

//Componentes criados para consulta
import { CstCidadesComponent } from './cst-cidades/cst-cidades.component';
 
@NgModule({
  declarations: [
    AppComponent, CstCidadesComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    PoModule,
    PoNotificationModule,PoDynamicModule,PoButtonModule,
    RouterModule.forRoot([])
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Mais uma vez vamos executar o comando ng serve -o para que o projeto seja executado e já aberto em nosso navegador, o resultado deve ser parecido com o seguinte

Erro de CORS ao executar teste no Angular

Pode ocorrer de ao tentar executar o teste com o comando ng serve não o sistema apresentar erro de Servidor não está respondendo, se isso ocorrer clique em inspecionar a página e vá em console, se estiver apresentando alguma falha relacionada a CORS é uma configuração de segurança do lado do servidor.

Falha de CORS

Para corrigir isso basta seguir um guia disponibilizado pela TOTVS, neste link para TOMCAT Configuração de CORS para ambiente TOMCAT ou este para JBOSS Configuração de CORS para ambiente JBOSS.

Outra observação importante é que para funcionar no menu no TOTVs sem erro ao buildar use o seguinte comando:

ng build --prod --base-href /PROJETO/

E ao cadastrar no TOTVs selecione “Programa THF”, só assim vai abrir como aba no sistema

5 thoughts on “Criando tela de consulta via API com Angular e PO UI

  1. Segui estes dois tutorias e até funcionou, rodando localmente em minha máquina (ainda que acessando a API Rest no servidor) e testando via postman também, porém no final não consegui colocar para funcionar dentro do Datasul, via menu.

    Já tentei de tudo, o que percebi (e não sei se é esta a razão e tb não sei de onde ele busco essa informação) é que ele está retornando um erro 404 (não encontrada) como se o endereço da API estivesse errado, e de fato analisando via DevTools (F12) notei que a chamada não está correta:
    erro:
    GET http://192.168.10.18:8080/cdp/api/v2/api_cidade (erro 404)

    Quando o endereço deveria ser: http://192.168.10.18:8080/api/cdp/v2/api_cidade/

    OBS(1): No cst-cidades.service.ts está correto =

    ApiRest = ‘http://192.168.10.18:8080/api/cdp/v2/api_cidade/’

    OBS(2): Rodando a aplicação fora do Datasul funciona perfeitamente, listando todas as cidades no browser.

    Alguém, tem noção do que posso estar errando, faltando tão pouco..kkk

    Sergio Nunes

    1. Bom dia novamente Sergio,
      fico muito feliz que os guias estejam ajudando.
      Não entendi bem se não está acessando o front-end pelo menu ou se não está acessando a API.

      Não tenho certeza se é este o problema mas talvez te ajude,

      Primeiro, tem que mapear o diretório onde as APIs vão ficar no seu servidor de aplicação, a TOTVs tinha um help sobre isso más ele sumiu,
      se for TomCat tem que alterar o arquivo apache-tomcat-9.0.31\conf\server.xml
      e incluir o diretório onde vai ficar as APIs na TAG

      Talvez esses links possam te orientar ainda mais:
      Configurando o Datasul-Valve no servidor Tomcat
      Implantação do Datasul-Valve – JBoss

      E em segundo, para incluir o projeto no menu, quando for fazer o build do projeto, não esqueça de informar uma base-href: ng build –prod –base-href /PROJETO/
      copie a pasta gerada no bin para o diretório webapps: apache-tomcat-9.0.31\webapps
      E quando for cadastrar no Totvs no programa BAS_PROG_DTSUL, na guia detalhes, em Nome Externo informe apenas o nome da pasta do projeto, na guia Opções, em template informe Programa THF e em interface selecione a opção WEB.

      Espero que essas informações possam te ajudar.

      1. Fabiano,

        Muito obrigado pela ajuda e pela iniciativa de postar os tutoriais. Segue respostas (espero que não esteja abusando demais..kk):

        “…Não entendi bem se não está acessando o front-end pelo menu ou se não está acessando a API.”
        ===> consigo acessar o front-end no browser da minha máquina local, onde desenvolvi a parte angular PO-UI, porém apontando a parte progress do servidor (API)

        “…Primeiro, tem que mapear o diretório onde as APIs vão ficar no seu servidor de aplicação,…”
        ===> Coloquei minha API (api_cidade.p) numa pasta padrão (E:\totvs\datasul\dts-12\ERP\ems2\cdp\api\v2\api_cidade.r)
        que está no propath do AppServer:

        “E:\totvs\datasul\dts-12\ERP\fnd\tty,E:\totvs\datasul\dts-12\ERP\fnd,
        E:\totvs\datasul\dts-12\ERP\cingo,E:\totvs\datasul\dts-12\ERP,
        E:\totvs\datasul\dts-12\ERP\ems2,E:\totvs\datasul\dts-12\ERP\ems5,
        E:\totvs\datasul\dts-12\ERP\hcm,E:\totvs\datasul\dts-12\ERP\eai,
        E:\totvs\datasul\dts-12\ERP\eai2,E:\totvs\datasul\dts-12\ERP\gp,
        E:\totvs\datasul\dts-12\ERP\crm,E:\totvs\datasul\dts-12\ERP\crm\database,
        E:\totvs\datasul\dts-12\ERP\crm\integracoes, E:\totvs\datasul\dts-12\ServidorAplicacaoTomcat\instance-8080\scripts-8080,
        E:\totvs\datasul\dts-12\ServidorAplicacaoTomcat\instance-8080\apache-tomcat-9.0.31”

        “se for TomCat tem que alterar o arquivo apache-tomcat-9.0.31\conf\server.xml
        e incluir o diretório onde vai ficar as APIs na TAG”
        ==> Essa parte não entendi, poderia mandar um exemplo ? qual a TAG ?

        “Talvez esses links possam te orientar ainda mais:
        Configurando o Datasul-Valve no servidor Tomcat”
        ===> Essa configuração do Valve (CORS) eu fiz – ok

        “…E em segundo, para incluir o projeto no menu, quando for fazer o build do projeto,
        não esqueça de informar uma base-href: ng build –prod –base-href /PROJETO/”
        ===> Feito dessa forma mesmo: ng build –prod –base-href /CSTCIDADES/

        “…copie a pasta gerada no bin para o diretório webapps: apache-tomcat-9.0.31\webapps”
        ===> Na verdade ele gerou a pasta DIST / cstCidades

        “…E quando for cadastrar no Totvs no programa BAS_PROG_DTSUL, na guia detalhes,
        em Nome Externo informe apenas o nome da pasta do projeto, na guia Opções,
        em template informe Programa THF e em interface selecione a opção WEB.”

        ===> Feito exatamente assim

        fiz uma serie de prints pena que não dá para enviar por aqui, facilitaria o seu entendimento de como fiz as coisas que estou dizendo.

        De qualquer forma agradeço antecipadamente pela ajuda,

        Sergio Nunes

  2. Olá Fabiano!

    Fiz os tutoriais e agradeço por compartilhar o seu conhecimento que já tem sido muito válido para mim.

    Cheguei até certo ponto, porém apareceu o erro de “CORS”. Configurei para o ambiente JBOSS – link: https://tdn.engpro.totvs.com.br/pages/viewpage.action?pageId=570375018.
    O erro persiste. Consigo fazer rodar via Postman e via navegador, mas via Angular/PO-UI não.

    O erro é: Requisição cross-origin bloqueada: A diretiva de mesma origem (same origin policy) impede a leitura do recurso remoto em http://10.96.111.20:8480/api/fnd/v1/api_cidade?josso_assertion_id=3EFD09B9C84EDDBC&josso_assertion_id=6E2B97C5DB709D0D&josso_assertion_id=175D31A53C968BA3&josso_assertion_id=DD123B98F2F3E902&josso_assertion_id=365ABBFBCD3E1173&josso_assertion_id=FE6F671D8415C286&josso_assertion_id=F333D9975336650A&josso_assertion_id=775FBBE7CB2C2CC5&josso_assertion_id=796232FACE4BC101&josso_assertion_id=5328DDB65C3D583F (motivo: falha na requisição CORS). Código de status: (null) .

    Tem alguma dica de outras configurações que posso verificar?
    Ronara Nunes

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.