1
votes

I am working on a webpage and I am trying to display data from firebase firestore on one of my components. The component is supposed to show all the related data on the page and do search from searchbar.

I am using components called: searchComponent and cardComponent.

  • cardComponent displays each data point.
  • searchComponent uses cardsService to get data from firestore and displays all cardComponents by passing the card from database using @input.

Everything is functional. But the code didn't work as I thought it would. When I tried to stream collection data from firestore in constructor the page would only load that data only if it is navigated with url or the page is refreshed. If I navigated the page by clicking a router link than data was not visible.

Once I changed to doing getting the snapshotChanges or valueChanges in ngOnInit function everything started working.

This was the Constructor code that didn't display data on router load.

constructor(public afs: AngularFirestore) {
this.cardsCollection = this.afs.collection('cards', ref => ref.orderBy('author', 'asc'));
this.cards = this.cardsCollection.snapshotChanges().map(changes => {
  return changes.map(a => {
    const data = a.payload.doc.data() as Card;
    data.id = a.payload.doc.id;
    return data;
  });
});

}

Currently I changed it to getting cardsCollection in constructor and getting changes in ngOnInit.

constructor(public afs: AngularFirestore) {
  this.cardsCollection = this.afs.collection('cards', ref => ref.orderBy('author', 'asc'));
}

ngOnInit() {
  this.cards = this.cardsCollection.snapshotChanges().map(changes => {
    return changes.map(a => {
      const data = a.payload.doc.data() as Card;
      data.id = a.payload.doc.id;
      return data;
    });
  });
}

This code works properly. But my question is why? Whats wrong with first code?

1

1 Answers

1
votes

constructor() is a javascript construct and may be called at any time, which may be before Angular has setup the component. ngOnInit() is called by Angular and is guaranteed to be called when the component is 'ready'.

Most likely the constructor call is just coming in too early and the reference top 'this.afs' isn't initialized.

More info: https://toddmotto.com/angular-constructor-ngoninit-lifecycle-hook

Angular lifecycle events:
https://angular.io/guide/lifecycle-hooks