0

I'm developing an application using Angular 6 angularfire2 firestore. At first everything looks good, I click (/list) the route to list my objects, the list is ok. But when I click /Home and then again click /list to list again, no list is shown, no errors in console. but if I refresh the page using F5 the list appears again.

Any ideas what am I doing wrong?

My service:



    import { AngularFirestoreCollection, AngularFirestoreDocument, AngularFirestore } from 'angularfire2/firestore';
    import { Personagem } from './../model/personagem';
    import { Observable } from 'rxjs/Observable';
    import { Injectable } from '@angular/core';

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

      personagens: Observable;
      personagemColl: AngularFirestoreCollection;
      personagemDoc: AngularFirestoreDocument;

      constructor(private afs: AngularFirestore) { 
        this.personagemColl = this.afs.collection('personagem', ref=> ref.orderBy('nome', 'asc'));

        this.personagens = this.personagemColl.snapshotChanges().map(changes=> {
          return changes.map(p => {
            const data = p.payload.doc.data() as Personagem;
            data.id = p.payload.doc.id;
            return data;
          });
        });
      }

      getPersonagens() {
        return this.personagens;
      }

      addPersonagem(personagem: Personagem) {
        this.personagemColl.add(personagem);
      }

      deletePersonagem(personagem: Personagem) {
        this.getPersonagemDoc(personagem)
        this.personagemDoc.delete();
      }

      updatePersonagem(personagem: Personagem) {
        this.getPersonagemDoc(personagem)
        this.personagemDoc.update(personagem);
      }

      getPersonagemDoc(personagem: Personagem) {
        return this.personagemDoc = this.afs.doc(`personagem/${personagem.id}`); 
      }
    }

My Component:



    import { Router } from '@angular/router';
    import { PersonagemService } from './../../services/personagem.service';
    import { Component, OnInit } from '@angular/core';
    import { Observable } from '@firebase/util';
    import { Personagem } from '../../model/personagem';

    @Component({
      selector: 'app-listar-personagem',
      templateUrl: './listar-personagem.component.html',
      styleUrls: ['./listar-personagem.component.css']
    })
    export class ListarPersonagemComponent implements OnInit {

      personagens: Personagem[];

      constructor(private personagemServ: PersonagemService,
        private router: Router) {

      }

      ngOnInit() {
        this.personagemServ.getPersonagens().subscribe(personagens => {
          this.personagens = personagens;
          console.log('lenght', this.personagens.length);
        });
      }

    }

I FIXED IT

I changed the service like this:



      //personagens: Observable;
      personagemColl: AngularFirestoreCollection;
      personagemDoc: AngularFirestoreDocument;

      constructor(private afs: AngularFirestore) { 
        this.personagemColl = this.afs.collection('personagem', ref=> ref.orderBy('nome', 'asc'));
      }

      getPersonagens$(): Observable {
        return this.personagemColl.snapshotChanges().map(changes=> {
          return changes.map(p => {
            const data = p.payload.doc.data() as Personagem;
            data.id = p.payload.doc.id;
            return data;
          });
        });
      }

And the list component like this:



      personagens: Personagem[];

      constructor(private personagemServ: PersonagemService,
        private router: Router) {

      }

      ngOnInit() {
        this.personagemServ.getPersonagens$().subscribe(
          personagens => {
            this.personagens = personagens;
          });
      }

Thank you guys

WSouBar
  • 71
  • 1
  • 5
  • 1
    You may find solutions in [this post](https://stackoverflow.com/q/43806492/1009922) (if `ngOnInit` is not called every time the list component becomes visible). – ConnorsFan May 18 '18 at 19:53

1 Answers1

2

Observables do not hold last values. Aka. when you subscribe to the personagens: Observable, you have to wait for something to push a new value there. So in your case, the first time you refresh, you subscribe to the observable before a value is pushed there. When the value is pushed, your list is initialized. When you move to /home and back to /list, you resubscribe to the observable, but since nothing new is pushed to that observable, your list remains uninitialized the second time.

You could look into BehaviourSubject, which is extended from Observable (http://reactivex.io/RxJava/javadoc/rx/subjects/BehaviorSubject.html)

enter image description here

Subject that emits the most recent item it has observed and all subsequent observed items to each subscribed Observer.

enter image description here

EDIT 1#

In addition, you do not terminate your subscriptions. If you do not terminate them, they are left open in the application, even when the component is destroyed, thus eventually creating a performance bottleneck.

this.personagemServ.getPersonagens().subscribe(personagens => {
          this.personagens = personagens;
          console.log('lenght', this.personagens.length);
        });

Here is a nice article about how to terminate subscriptions gracefully.

Angular/RxJs When should I unsubscribe from `Subscription`

Karl Johan Vallner
  • 3,980
  • 4
  • 35
  • 46