-1

I have two methods, one makes a push value and the other makes a patchValue, I need the push value to be finalized so that the patch value method can work correctly. I call them both in an ngAfterViewInit, I would like to know a way to do this without calling the patch value method inside the push value method.

Both Methods are called here

ngAfterViewInit(): void {
        this.inicializarListaGrupoAnaliseCae();
        this.iniciarDadosVisualizar();
        //this.iniciarSituacaoCadastro();
        this.cdr.detectChanges();
    }

PatchValue Method:

iniciarDadosVisualizar() {
        if(this.isVisualizando || this.isEdit){
            this.dadosVisualizar.grupoAnaliseCae.noGrupoAnaliseCae='CONSELHO';
            this.formPesquisar.controls['descricaoMotivo'].patchValue(this.dadosVisualizar.descricaoMotivo);
            this.formPesquisar.controls['grupoAnaliseCae'].patchValue(this.dadosVisualizar.grupoAnaliseCae);
            this.formPesquisar.controls['categoriaMembro'].patchValue(this.dadosVisualizar.grupoAnaliseCae);
            this.formPesquisar.controls['situacaoMotivo'].patchValue(this.dadosVisualizar.situacaoMotivo);
        }
        if(this.isVisualizando){
            this.desabilitarCampos()
        }
    };

Push Value Method:

private inicializarListaGrupoAnaliseCae(): void {
        this.grupoAnaliseCaeService
            .findAll()
            .subscribe(res => {
                res.forEach((grupoAnaliseCae: GrupoAnaliseCae) => {
                    if(grupoAnaliseCae.nuNivelGrupo==null){
                    this.listaGrupoAnaliseCae.push({ label: grupoAnaliseCae.noGrupoAnaliseCae, value: grupoAnaliseCae });
                    this.formataNomeGrupo();
                    }
                });
            });
    }

4 Answers4

0

Once you've introduced a single point of reactive paradigm (the subscription here) in your program, all dependent subsequent statements should be reactive as well. The quickest fix in your scenario would be to call the dependent function inside the subscription.

ngAfterViewInit(): void {
  this.inicializarListaGrupoAnaliseCae();
  this.cdr.detectChanges();
}

private inicializarListaGrupoAnaliseCae(): void {
  this.grupoAnaliseCaeService
    .findAll()
    .subscribe(res => {
      res.forEach((grupoAnaliseCae: GrupoAnaliseCae) => {
        if (grupoAnaliseCae.nuNivelGrupo == null) {
          this.listaGrupoAnaliseCae.push({
            label: grupoAnaliseCae.noGrupoAnaliseCae,
            value: grupoAnaliseCae
          });
          this.formataNomeGrupo();
        }
      });
      this.inicializarListaGrupoAnaliseCae();      // <-- call function here
    });
}

You could learn more about asynchronous data here.

ruth
  • 29,535
  • 4
  • 30
  • 57
0

I assume your initial values (pushValues) are coming from an HTTP service which can take some time to resolve. You are essentially looking for a state here, meaning you need to know the state of the form before patching. If this is the case then you can use a BehaviorSubject or just a normal variable to track the state whether the form is ready to be patched or not.

private isFormInitialized = false;

In your initializer observable:

private inicializarListaGrupoAnaliseCae(): void {
    this.grupoAnaliseCaeService
        .findAll()
        .subscribe(res => {
            res.forEach((grupoAnaliseCae: GrupoAnaliseCae) => {
                if(grupoAnaliseCae.nuNivelGrupo==null){
                this.listaGrupoAnaliseCae.push({ label: grupoAnaliseCae.noGrupoAnaliseCae, value: grupoAnaliseCae });
                this.formataNomeGrupo();
                }
            });

            // update form state tracker
            this.isFormInitialized = true;
        });
}

Now use the state to check before you patch:

iniciarDadosVisualizar() {
    if(this.isFormInitialized && this.isVisualizando || this.isEdit){
    ... // other logic
};
Touhid Rahman
  • 533
  • 5
  • 14
0

The first method is asynchronous, and doesn't return anything which is the issue. Instead of subscribing inside that method, you should return the observable. Then in ngAfterViewInit you can subscribe to it and call the 2nd method when it has completed.

I'm not sure if you need to return anything in your Observable for the other one, so Observable<void> or a different return might be more appropriate.

The new push method

private inicializarListaGrupoAnaliseCae(): Observable<void> {
        return this.grupoAnaliseCaeService
            .findAll()
            .pipe(
                tap(res => {
                    res.forEach((grupoAnaliseCae: GrupoAnaliseCae) => {
                        if(grupoAnaliseCae.nuNivelGrupo==null){
                        this.listaGrupoAnaliseCae.push({ label: grupoAnaliseCae.noGrupoAnaliseCae, value: grupoAnaliseCae });
                        this.formataNomeGrupo();
                        }
                    });
                })
           );
    }

New ngAfterViewInit

ngAfterViewInit(): void {
        this.inicializarListaGrupoAnaliseCae().subscribe(() => {
          this.iniciarDadosVisualizar();
          //this.iniciarSituacaoCadastro();
          this.cdr.detectChanges();
        });
        
    }

Note, I'm not managing the subscription here. If your findAll() method is an HTTP request it should complete once the data loads so it won't be an issue, but if its something else you may need to look into how you want to unsubscribe.

cjd82187
  • 3,468
  • 3
  • 15
  • 19
-1

Try converting the observable to a promise like so:

private async inicializarListaGrupoAnaliseCae(): Promise<any> {
        return this.grupoAnaliseCaeService
            .findAll()
            .toPromise().then(res => {
                res.forEach((grupoAnaliseCae: GrupoAnaliseCae) => {
                    if(grupoAnaliseCae.nuNivelGrupo==null){
                    this.listaGrupoAnaliseCae.push({ label: grupoAnaliseCae.noGrupoAnaliseCae, value: grupoAnaliseCae });
                    this.formataNomeGrupo();
                    }
                });
            });
    }

Then await this promise in ngAfterViewInit like so:

async ngAfterViewInit(): void {
    await this.inicializarListaGrupoAnaliseCae();
    this.iniciarDadosVisualizar();
    //this.iniciarSituacaoCadastro();
    this.cdr.detectChanges();
}

Here is a StackBlitz illustration.

ViqMontana
  • 5,090
  • 3
  • 19
  • 54