0

I Want to populate a page with data from the server, and be able to change the information, for This I'm using formbuilder to bring data from the server as default value using this:

 createForm(){
    this.getGeral()
    this.getTiposTarefas()
    this.formulario = this.fb.group({
      'tipo_tarefa':[this.tarefa.tipoTarefa.id, Validators.compose([Validators.required])], // Cant set default values cuz the array is object is undefined
      'data_tarefa': [this.tarefa.data_tarefa, Validators.compose([Validators.required])],// Cant set default values cuz the array is object is undefined
      'inicio_tarefa': [this.tarefa.inicio, Validators.compose([Validators.required])],// Cant set default values cuz the array is object is undefined
      'fim_tarefa': [this.tarefa.fim, Validators.compose([Validators.required])]// Cant set default values cuz the array is object is undefined
   });
  }

But I it gets undefined. I Tried console.log() inside de subscribe function and the object 'Tarefa' is populated, but out of the function scope it is not.

    import { Component, OnInit } from '@angular/core';
    import { NavParams, ModalController } from '@ionic/angular';
    import { TarefadetalheService } from './tarefadetalhe.service';
    import { Tarefa } from '../../models/tarefa.model';
    import { TipoTarefa } from '../../models/tipotarefa.model';

    import { FormGroup, FormBuilder, Validators } from '@angular/forms';
    @Component({
      selector: 'app-tarefas-detalhe',
      templateUrl: './tarefas-detalhe.page.html',
      styleUrls: ['./tarefas-detalhe.page.scss'],
    })
    export class TarefasDetalhePage implements OnInit {
     idTarefa = null
     tarefa: Tarefa
     tiposTarefas : TipoTarefa[]
     formulario: FormGroup
      constructor(
        private navParams: NavParams,
        private getTarefaDetalhe: TarefadetalheService,
        private modalController:ModalController,
        public fb: FormBuilder) {   }

      ngOnInit() {

        this.createForm()
      }

      getGeral(){
        this.idTarefa = this.navParams.get('id_tarefa');
        this.getTarefaDetalhe.recuperaDetalhes().subscribe((data: Tarefa)=>{ //passar o id da tarefa como parametro no recupera detalhes
        this.tarefa = data
       })
      }

  getTiposTarefas(){
    this.getTarefaDetalhe.recuperaTiposTarefas().subscribe((data: TipoTarefa[])=>{
    this.tiposTarefas = data
    console.log(this.tiposTarefas) // here it has information
    })
    console.log(this.tiposTarefas) // here it has not information
  }

  createForm(){
    this.getGeral()
    this.getTiposTarefas()
    this.formulario = this.fb.group({
      'tipo_tarefa':[this.tarefa.tipoTarefa.id, Validators.compose([Validators.required])], // Cant set default values cuz the array is object is undefined
      'data_tarefa': [this.tarefa.data_tarefa, Validators.compose([Validators.required])],// Cant set default values cuz the array is object is undefined
      'inicio_tarefa': [this.tarefa.inicio, Validators.compose([Validators.required])],// Cant set default values cuz the array is object is undefined
      'fim_tarefa': [this.tarefa.fim, Validators.compose([Validators.required])]// Cant set default values cuz the array is object is undefined
   });
  }
 closeModal()
 {
   this.modalController.dismiss();
 }
}

When I Run Ionic serve it throws me the error below and I can't set default values on the formcontrols:

enter image description here

MY HTML:

<ion-content padding *ngIf="tarefa != null">
  <form [formGroup]="formulario">
    <h4>
      <ion-icon name="list-box"></ion-icon> Geral
    </h4>
    <ion-grid>
      <ion-row>
        <ion-col size="8">
            <ion-label position="floating">Tipo de Tarefa</ion-label>
          <ion-select [formControlName]="tipo_tarefa" okText="Confirmar" cancelText="Cancelar">
            <ion-select-option *ngFor="let tipo of tiposTarefas" [value]="tipo.id">{{tipo.descricao}}</ion-select-option>
          </ion-select>
        </ion-col>
      </ion-row>
    </ion-grid>
    <h4>
      <ion-icon name="calendar"></ion-icon> Horário
    </h4>
    <ion-item-divider></ion-item-divider>
    <ion-grid>
      <ion-row>
        <ion-col size="5">
          <ion-label position="stacked">Data</ion-label>
          <ion-datetime  [formControlName]="data_tarefa" display-format="DD-MM-YYYY" max="2050-10-31" picker-format="DD-MM-YYYY"></ion-datetime>
        </ion-col>
        <ion-col size="3">
          <ion-label position="stacked">Inicio</ion-label>
          <ion-datetime  [formControlName]="inicio_tarefa" display-format="HH:mm" picker-format="HH:mm" ></ion-datetime>
        </ion-col>
        <ion-col size="3">
          <ion-label position="stacked">Fim</ion-label>
          <ion-datetime  [formControlName]="fim_tarefa" display-format="HH:mm" picker-format="HH:mm"></ion-datetime>
        </ion-col>
      </ion-row>
    </ion-grid>
    <h4>
      <ion-icon name="person"></ion-icon> Cliente
    </h4>
    <ion-item-divider></ion-item-divider>
    <ion-grid>
      <ion-row>
      </ion-row>
    </ion-grid>
  </form>
</ion-content>
hygull
  • 8,464
  • 2
  • 43
  • 52
Tiago Silveira
  • 267
  • 4
  • 14
  • 2
    Conclusion: you have to do the processing inside of the subscribe callback. Execute the line `this.formulario = this.fb.group(...)` inside of `getTiposTarefas` (in the callback). – ConnorsFan Mar 19 '19 at 19:12
  • Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – ConnorsFan Mar 19 '19 at 19:15
  • 1
    Initiate the this.formulario = this.fb.group({ form creation only after you have received all the data from the 2 functions you are calling before it. – Manzurul Mar 19 '19 at 19:18
  • @Manzurul, how can I do that? Sorry but I'm new on TS. – Tiago Silveira Mar 19 '19 at 19:19
  • @TiagoSilveira Posted an answer. – Manzurul Mar 19 '19 at 19:28
  • @ConnorsFan It's a good Idea but I think it will make the code a bit hard to understand... Well, If i'm putting the value of the 'data' inside the this.tiposTarefa. Why i can't acess this data out of the subscribe? – Tiago Silveira Mar 19 '19 at 19:55
  • @TiagoSilveira - In fact, you can access the value outside of the callback. The problem is that you try to access it **before** the callback has been executed. The subscribe callback is called later (asynchronously). – ConnorsFan Mar 19 '19 at 19:58
  • And how Can I make this asynchonous, so this way the form will be intanciated when I get the data,. – Tiago Silveira Mar 19 '19 at 20:01
  • It is already asynchronous, and you cannot make it synchronous. To use the data as early as possible, initialize your form inside of the subscribe callback. If you want to make it "less confusing" (maybe), you can pass a callback to `getTiposTarefas`, so that the initization code would still appear in the `createForm` method. – ConnorsFan Mar 19 '19 at 20:07

1 Answers1

1

Remove the function getTiposTarefas() and then make the following changes.

createForm(){
 this.getGeral();
 this.getTarefaDetalhe.recuperaTiposTarefas().subscribe((data: TipoTarefa[])=>{
 this.tiposTarefas = data;
 this.formulario = this.fb.group({...put the fields...});
  console.log(this.tiposTarefas) // here it has information
 })
}

Update: You need to initialize this tarefa: Tarefa object first. See below

tarefa: Tarefa =  {
  comentarios: '',
  data_tarefa: '',
  descricao: '',
  fim: '',
  id_aprovador: '',
  id_cliente: '',
  id_criador: '',
  id_sala: '',
  id_sistema: '',
  id_solicitante: '',
  inicio: '',
  nome_aprovador: '',
  nome_cliente: '',
  nome_criador: '',
  nome_sistema: '',
  nome_solicitante: '',
  numero: 0,
  participante: [],
  status_tarefa: 0,
  tarefa: '',
  tipoTarefa: {
      id:'',
      interna: null,
      descricao: ''
  }
};

It should work fine then.

Manzurul
  • 633
  • 6
  • 11