2
votes

What I'm using

  • Angular
  • Firebase

What I'm doing

  • I click on an item from a collection list

  • This item links to a document view

  • I display the document

  • Instead of using valueChanges(), I need to update the returned date.

  • I update the returned date by using snapshotChanges()

The Issue

  • This mostly works fine and returns the data and I have correctly formatted the returned date

  • However, the consoles prints the document 5 times

Question

  1. Have I approached this correctly? As this is the approach I'll probably aim to use to fetch the downloadURL from storage too
  2. Why is the document appearing 5 times in the console? (Screenshot attached)

Any assistance would be greatly appreciated! :)

Component TS

import { Component, OnInit } from '@angular/core';

// Firestore
import { Observable } from 'rxjs/Observable';
import { AngularFirestore, AngularFirestoreDocument } from 'angularfire2/firestore';

// Routes
import { Router, ActivatedRoute } from '@angular/router';

// Moment JS
declare var moment: any;

@Component({
  selector: 'app-albums-detail',
  templateUrl: './albums-detail.component.html',
  styleUrls: ['./albums-detail.component.css']
})

export class albumsDetailComponent implements OnInit {

  folderId: string;
  albumId: string;

  private albumDoc: AngularFirestoreDocument<any>;
  album: Observable<any>;

  constructor(
    private readonly afs: AngularFirestore,
    private activatedRoute: ActivatedRoute,
    private router: Router) { }


  ngOnInit() {

    // Look at the url for the Folder and album ID and set the local variable
    this.activatedRoute.params.forEach((urlParameters) => {
      this.folderId = urlParameters['folderId'];
      this.albumId = urlParameters['albumId'];
    });

    // Return the albums list
    this.getalbumData();

  }

 
  getalbumData() {
    this.albumDoc = this.afs.doc(`folders/${this.folderId}/albums/${this.albumId}`);
    //this.album = this.albumDoc.valueChanges();

    this.album = this.albumDoc.snapshotChanges().map(action => {

      const id = action.payload.id;
      const data = action.payload.data();

      // Get the date from each album
      var albumDateTimestamp = data.album_date;

      // Convert the unix value and format it based on the users locale setting
      var albumDateISO = moment(albumDateTimestamp).format("DD/MM/YYYY");

      // Create a new 'name' to use in the HTML binding
      data.formattedDate = albumDateISO;

      console.log(data);

      return { id, ...data };

    });

  }
}

Component HTML

<h1> {{ (album | async)?.album_title }} </h1>
<div>
  {{ (album | async)?.album_title }}
  {{ (album | async)?.formattedDate }} 
  {{ (album | async)?.album_client }}
  {{ (album | async)?.album_reference }}
</div>

UPDATE

I've asked this question in a couple of places and tweeted a few people without much luck, so i've tried a new way. I'm not entirely sure it's clean, but it works. It's not using AngularFire anymore as I can't for the life of me figure out why it prints to the console so many times. I took an example straight from the firestore docs. I have a bunch of global variables which i update after grabbing the data and use that for my data binding. It feels like it's fetching / reading the data each time I load the page. Is there a way of checking?

If anyone can let me know if this is a legitimate way of performing this action, that would be awesome :D

 getProjectData() {


    var db = firebase.firestore();

    var docRef = db.collection(`folders/${this.folderId}/albums`).doc(`${this.albumId}`);

    docRef.get().then((doc) => {
      if (doc.exists) {
        console.log("Document data:", doc.data());
        var data = doc.data();
        var id = doc.id;
        this.shazam(data, id);
      } else {
        console.log("No Such Document");
      }
    });

  }



shazam(data, id) {


    var albumTimeStamp = data.album_date;

    // Convert the unix value and format it based on the users locale setting
    var albumDateIso = moment(albumTimeStamp).format("DD/MM/YYYY");

    // Create a new 'name' to use in the HTML binding
    data.formattedDate = albumDateIso;

    this.albumTitle = data.project_title;
    this.albumDate = data.formattedDate;

  }

enter image description here

1

1 Answers

0
votes

Could you also add a log statement to ngOnInit? My besteht guess is is that the component gets initialized multiple times.