Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

[Dúvida] Exibição de dados consumidos de API

Boa tarde :)

Estou tentando fazer um formulário semelhante a esse da aula para complementar o estudo de consumo de API, então usei a API de estados brasileiros do IBGE (https://servicodados.ibge.gov.br/api/v1/localidades/estados) e gostaria de fazer tipo uma seleção dropdown para exibir o nome dos estados para o usuário selecionar. Mas o código está com algum erro que não consigo entender (acho que é mau uso da diretiva NgFor, mas mesmo assim não estou conseguindo corrigir)... Ao invés de aparecer um dropdown com todos os estados, está gerando um monte de menus, cada um deles exibe um único estado da API. Se alguém conseguir me ajudar... o código está abaixo:

Service:

import { Estado } from './../components/cidade-estado/estado';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

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

  private readonly url_API_estados = 'https://servicodados.ibge.gov.br/api/v1/localidades/estados'
  constructor(private http: HttpClient) { }

  listarEstados(){
    return this.http.get<Estado[]>(this.url_API_estados);
  }
}

Interface Estado:

export interface Estado {
  id?: number
  sigla?: string
  nome?: string
};

Componente:

import { ConsultaEstadoService } from './../../services/consulta-estado.service';
import { Component, OnInit } from '@angular/core';
import { Estado } from './estado';

@Component({
  selector: 'app-cidade-estado',
  templateUrl: './cidade-estado.component.html',
  styleUrls: ['./cidade-estado.component.scss']
})

export class CidadeEstadoComponent implements OnInit {

  estados?: Estado[];

  constructor(private service: ConsultaEstadoService){
  }
  ngOnInit(){
    this.service
          .listarEstados()
          .subscribe(resultado => this.estados = resultado);
  }

}

Template: Obs.: estou utilizando DevExtreme só para fins de estilização mesmo.

<div>
  <div>
    <p>Estado:</p>
     <dx-select-box *ngFor="let estado of estados"
        [items]="[{nome: estado.nome}]"
        displayExpr="nome"
        placeholder="Selecione o Estado..."
        [showClearButton]="true"
      ></dx-select-box>
</div>

Muito obrigada!

5 respostas

Olá Larissa, tudo bom?

Faz um teste na sua aplicação, ao inves de fazer o ng-for na tag <dx-select-box>, faz na div pai.

<div *ngFor="let estado of estados">
    <p>Estado:</p>
     <dx-select-box 
        [items]="[{nome: estado.nome}]"
        displayExpr="nome"
        placeholder="Selecione o Estado..."
        [showClearButton]="true"
      ></dx-select-box>
</div>

E faz um teste de mesa, colocar um console.log(this.estados) dentro do subscribe para ver se ele está retornando certinho.

ngOnInit(){
    this.service
          .listarEstados()
          .subscribe(resultado => {
              this.estados = resultado;
              console.log(this.estados);
              });
  }

Testa ai e me fala se deu certo.

Oi, Diego! Tudo bem, e com você?

Eu já tinha feito o teste do console.log e está retornando o array sim! Testei agora o que você sugeriu de colocar o ngFor na div pai, a única coisa que mudou foi que agora a palavra "Estado" que está na tag p também aparece, aqui está o print:

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

solução!

Olá, Larissa!

O problema está no uso da diretiva *ngFor. Quando você coloca o *ngFor no dx-select-box, ele irá criar um select-box para cada estado que está no array "estados". Para resolver isso, você deve remover o *ngFor do dx-select-box e definir a propriedade "items" com o array "estados" diretamente.

Seu código ficaria assim:

<div>
  <div>
    <p>Estado:</p>
     <dx-select-box
        [items]="estados"
        displayExpr="nome"
        valueExpr="sigla"
        placeholder="Selecione o Estado..."
        [showClearButton]="true"
      ></dx-select-box>
  </div>
</div>

Além disso, adicionei a propriedade "valueExpr" para definir que a sigla do estado será usada como valor selecionado.

Exemplo da documentação:

 <div class="dx-fieldset-header">EditBox</div>
      <div class="dx-field">
        <div class="dx-field-label">Product</div>
        <div class="dx-field-value">
          <dx-select-box
            #selectBox
            [dataSource]="productsDataSource"
            [acceptCustomValue]="true"
            displayExpr="Name"
            valueExpr="ID"
            [value]="product"
            (onCustomItemCreating)="addCustomItem($event)"
          ></dx-select-box>
        </div>
      </div>

Espero ter ajudado!

Bom dia, Silvino! Muito obrigada, deu certo aqui :) Precisei fazer pequenos ajustes, mas a sua solução me deu o norte e agora está tudo funcionando. Mais uma vez, muito obrigada!

Olá Larissa,

Gostaria de começar dizendo que estou muito feliz por saber que você está focada nos seus estudos de tecnologia na Alura. É realmente impressionante ver alguém se dedicando tanto a uma área e buscando se aprimorar constantemente.

Além disso, gostaria de perguntar como você conseguiu realizar tantas formações completas em um curto período de tempo. Vi que você conseguiu completar diversos cursos em questão de dias, o que é realmente impressionante.

Estou curioso para saber qual é o segredo por trás de sua produtividade e como você consegue se manter tão focada e disciplinada. Seria ótimo se pudéssemos conversar mais sobre isso e compartilhar algumas dicas e estratégias.

Parabéns por seus esforços e sucesso em sua jornada de aprendizado!

Obs: Não consegui falar com você em outro lugar por isso postei aqui mesmo.

Atenciosamente, Silvino Miranda