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

angular carregar Json de forma assíncrona

Estou com problema novamente, com relação a forma assíncrona de carregamento do Java script. conforme no topico que eu abri anteriormente.

Desta vez consigo fazer os dados serem carregados, porem eles não são exibidos por completo no formulário. Geralmente só aparece a partir do terceiro campo, e os três primeiros ficam vazios. segue como está o código atualmente.

service de conexão com WS

@Injectable()
export class FornecedorApiService {
  private _fornecedor: Fornecedor = new Fornecedor();

  constructor(private _api: Api) { }

  public getFornecedorPorId(id: number): Observable<Fornecedor> {
    return this._api.buscaJsonDaApiPorId('fornecedor', id);
  }
 public getEstados(): Observable<Uf> {
    return this._api.buscaJsonDaApiPorUrl('uteis/estados');
  }
}

appComponent

export class AlterarDadosFornecadorComponent implements OnInit {

  @Input() fornecedor: Fornecedor = new Fornecedor();
  public formFornecedor: FormGroup;
  public endereco: Endereco = new Endereco();
  public estadosElements: SelectItem[] = [];

  constructor(
    private _fb: FormBuilder,
    private _fornecedorService: FornecedorApiService
  ) { }

  ngOnInit() {
    if (this.fornecedor.id == null) {
      this._fornecedorApi
        .getFornecedorPorId(1)
        .subscribe(data => {

          this.fornecedor = <Fornecedor>data;
          this._fornecedorService
            .getEstados()
            .subscribe((dataUf: Object[]) => {
              const estados: Array<Uf> = new Array<Uf>();
              dataUf.forEach((elemento: Uf) => {
                estados.push(elemento);
        this.constroiFormulario();

            });
        });

    }

  }
  constroiFormulario() {
    this.formFornecedor = this._fb.group({
      nome: [this.fornecedor.nome],
      cnpj: [this.fornecedor.cnpj],
      contato: [this.fornecedor.nomeContato],
      telefone: [this.fornecedor.telefone],
      email: [this.fornecedor.email],
      formEndereco: this._fb.group({
        bairro: [this.fornecedor.endereco.bairro],
        cep: [this.fornecedor.endereco.cep],
        rua: [this.fornecedor.endereco.rua],
        complemento: [this.fornecedor.endereco.complemento],
        formEstado: this._fb.group({
          nome: [this.fornecedor.endereco.estado.nome],
          estado: [this.fornecedor.endereco.estado.uf]
        })
    });
  }
}

HTML

<form [formGroup]="formFornecedor">
 <table>
          <tr>
            <td>
              <b>Nome  </b>
            </td>
            <td>
              <input type="text" pInputText formControlName="nome">
            </td>
          </tr>
          <tr>
            <td>
              <b>CNPJ: </b>
            </td>
            <td>
              <input type="text" pInputText formControlName="cnpj">
            </td>
          </tr>
              <td>
              <b>Nome para contato: </b>
            </td>
            <td>
              <input type="text" pInputText formControlName="contato">
            </td>
          </tr>
---mais campos de formulário --
<table formName="formGrupEndereco">
          <tr>
            <td>
              <b>Rua: </b>
            </td>
            <td>
              <input type="text" pInputText formControlName="rua">
            </td>
          </tr>
---mais campos de formulário --
    <b>Estado: </b>
            </td>

            <td>
            <input type="text" pInputText formControlName="estado">
        </td>
   </tr>
</form>

Em resumo minha última ideia foi fazer a subscribe no fornecedor e dentro do fornecedor fazer a subscribe no estado.

Ele exibe os dados porem os três primeiros campos aparece como undefined e o campo no HTML fica vazio, após isto dá tempo de carregar o fornecedor do Json e preenche os outros campos porem os primeiros permanecem vazios.

já tentei colocar o método constroiFormulario() fora do subscrible porem ai não aparece nenhum dados.

Acredito que essa forma não seja a correta, como eu faço para pegar os dados de mais de um WS diferente e preencher o form no html. (OBS: se alguém souber de um artigo que possa me ajudar a estudar mais sobre esta parte do angular, eu agradeço)

4 respostas
solução!

Boa noite, Matheus! Como vai?

Nesse caso aí o mais indicado é vc usar o forkJoin() do RxJS.

No seu caso, ficaria algo assim:

Observable.forkJoin(
     this._fornecedorApi.getFornecedorPorId(1),
     this._fornecedorService.getEstados()
).subscribe(res => console.log(res));

Onde res será um vetor contendo na primeira posição o resultado do primeiro Observable do forkJoin(), na segunda posição o resultado do segundo Observable e assim por diante. E talvez esse código mude um pouco dependendo da versão do RxJS que esteja sendo utilizada no seu projeto.

OBS: se alguém souber de um artigo que possa me ajudar a estudar mais sobre esta parte do angular, eu agradeço.

Segue o link da documentação do Angular que trata sobre a utilização do RxJS. O ideal é que vc dê uma lida em toda a seção que trata sobre esse assunto, intitulada "Observables & RxJS".

https://angular.io/guide/observables

Qualquer coisa é só falar!

Grande abraço e bons estudos!

infelizmente o erro permanece somente apos algum tempo que os dados são carregados com isso os primeiros ficam vazio, tem como eu colocar para carregar o formulário somente apos estar com todos os dados do fornecedor?

o código ficou assim:

combineLatest(
this._fornecedorService.getFornecedor(1),
          this._fornecedorService.getEstados()        
        ).subscribe(data => {
          console.log(data[0]);
        this.fornecedor = <Fornecedor>data[0];
          this.estados =  <estados>data[1];


          this.constroiFormulario();

        });

mesma coisa com o forkJoin

consegui resolver mais não sei se foi a melhor solução.

coloquei um boolean no formulário e quando finaliza o subscrible ele muda para true

html

<form *ngIf='carrega'>
---codigo--
</form>

appcomponent

combineLatest(
this._fornecedorService.getFornecedor(1),
          this._fornecedorService.getEstados()        
        ).subscribe(data => {
          console.log(data[0]);
        this.fornecedor = <Fornecedor>data[0];
          this.estados =  <estados>data[1];


          this.constroiFormulario();
carrega = true
        });

sé souberem uma solução melhor o essa realmente e a solução, estou achando um pouco ruim

Boa tarde, Matheus! Como vai?

Essa realmente é uma solução possível! No entanto, a boa prática seria fazer aquilo que eu te falei no seu outro tópico: abrir um popup de loading antes do envio das requisições avisando o usuário que os dados estão sendo carregados e fechar ele após tudo estar carregado. Assim o usuário veria esse popup enquanto os dados estivessem sendo carregados e não teria acesso ao formulário. Ficaria algo como:

// aqui o popup deve ser aberto.
Observable.forkJoin(
     this._fornecedorApi.getFornecedorPorId(1),
     this._fornecedorService.getEstados()
).subscribe(res => {
     console.log(res);

     // no final do processamento da resposta o popup 
     // deve ser fechado.
});

Grande abraço e bons estudos!