0

I've this simple app where '/personas' shows a list of Persona objects. There is also a button to add another person, which send to you to /personas/agregar. There you can create a new object and send it to firebase. Once you do it, the server should take you to /personas again and you should see all objects, however it doesn't shows the new one unless you refresh.

This is the code (when you submit the form it trigger guardarPersona() method):

personas.component.ts:

export class PersonasComponent implements OnInit {

  personas: Persona[] = [];

  constructor(private personasService: PersonasService, private router: Router){}

  ngOnInit(): void {

    this.personasService.obtenerPersonas().subscribe(
      (personas: Persona[]) => {
        this.personas = personas;
        this.personasService.setPersonas(personas);
      }
    );

  }
  
  personaAgregada(persona: Persona){
    this.personas.push(persona);
  }

  agregar(){
    this.router.navigate(['personas/agregar'])
  }

}

formulario.component.ts:

guardarPersona(){
    if(this.id){
      this.personasService.modificarPersona(this.id, this.nombreInput, this.apellidoInput);
    }else{
      this.personasService.agregarPersona(new Persona(this.nombreInput, this.apellidoInput));
    }
    this.router.navigate(['personas']);
  }

persona.service.ts:

setPersonas(personas: Persona[]){
    this.personas = personas;
  }

  obtenerPersonas(){
    return this.dataService.cargarPersonas();
  }

agregarPersona(persona: Persona) {
    if(this.personas == null){
      this.personas = [];
    }
    this.personas.push(persona); 
    this.dataService.guardarPersonas(this.personas);
  }

data.services.ts:

cargarPersonas(){
        return this.httpClient.get<Persona[]>('https://listado-personas-53faf-default-rtdb.firebaseio.com/personas.json');
    }
    

    guardarPersonas(personas: Persona[]){
        this.httpClient.put(this.url + '.json', personas).subscribe(
            response => {console.log(`Datos enviados correctamente: ${response}`)},
            error => {console.log(`Error al enviar los datos: ${error}`)}
        );
    }

I've tried to solve it following this, using NgZone but it din't worked:

this.ngZone.run(() =>i {
    this.router.navigateByUrl('personas');
    });

I also tried with reloading the page after navigate but it neither send the information to firebase:

this.router.navigate(['personas']).then(() => {
    window.location.reload();
});

Then I tried with modifying ngOnInit based in this thread:

ngOnInit() {    
    this.router.events.subscribe(
      (event: Event) => {
             if (event instanceof NavigationEnd) {
                  this.personasService.obtenerPersonas().subscribe(
                    (personas: Persona[]) => {
                      this.personas = personas;
                      this.personasService.setPersonas(personas);
                    }
                  );
             }
      });
  }

But I get no overload matches this call error

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Manu
  • 25
  • 6
  • This is because `ngOnInit` fires once the component is created and if you navigate back to the list, the component is already created, so `ngOnInit` won't fire once again. Subscribing to the routing event is a good idea or you move the api call to a service and call it if necessary. – derstauner Mar 02 '23 at 18:36
  • The strange thing is that if I delete the navigate sentence, when adding a person and press navigator's back button it shows the updated list, and when using navigate I asume that it's creating the component again... Even I tried copying the ngOnInit script and implement ngOnChange but doesn't work either – Manu Mar 03 '23 at 18:10

1 Answers1

0

Doing some test I realized that I was wrong, ngOnInit() was executing after navigate(), however it wasn't showing the updated list because guardarPersonas() takes too long and ngOnInit() gets the list before it's updated.

I "solve" this by setting a timeout on navigate(), but I wonder if it's a better way to do this, for example waiting for httpClient.put to finish.

Manu
  • 25
  • 6
  • 1
    **No**, You can not trust setting a time. You need call to navigate "inside subscribe" or, if you're using ChangeDetectionStrategy.OnPush use [markForCheck](https://angular.io/api/core/ChangeDetectorRef#usage-notes) – Eliseo Mar 08 '23 at 17:31
  • @Eliseo Thanks! That's what I needed! I injected ```Router``` to ```DataService``` and call ```navigate()``` inside subscribe and it's working perfect now. – Manu Mar 08 '23 at 20:14