Search code examples
firebase-storagegoogle-cloud-firestoreangularfire5

AngularFire / FireStore - getDownloadURL


What I'm using

  • AngularFire
  • FireStore
  • New AngularFire syntax for Firestore

What I'm trying to do

  • get the download URL for each returned image

Issue

  • I'm getting the download URL for the first image and applying it to a global variable.
  • If four images are in storage, four are returned, but will all be the same image, opposed to four unique ones

Question

  • I'm using the new AngularFire Firestore syntax to fetch the data
  • How would I loop through each of the returned images and bind them to my HTML?

Component TS

  getIssueImages() {

    this.albumsCollection = this.afs.collection<any>(/albums/${albumId}/images`);
    this.albums = this.albumsCollection.snapshotChanges().map(actions => {
      return actions.map(a => {

        const data = a.payload.doc.data();

        const id = a.payload.doc.id;

        console.log(data);

        // Firebase Reference
        var storage = firebase.storage();

        // Get the image storage reference
        var image = data.image_thumbnail;

        //Create an image reference to the storage location
        var imagePathReference = storage.ref().child(image);

        // Get the download URL and set the local variable to the result (url)
        imagePathReference.getDownloadURL().then((url) => {
          this.image_thumbnail = url;
        });

        return { id, ...data };

      });
    });

  }

Component.HTML

  • As expected, this correctly returns the unique storage references of each image, but not the unique download URL references.

<ul>
  <li *ngFor="let image of images | async">
    {{ image.image_thumbnail }}
  </li>
</ul>

**Component.HTML - Incorrect **

  • So this one is trying to reference the firebase storage downloadURL that i'm trying to fetch from my function in my component.ts. As expected, I'm not looping through each one, an instead probably getting just the first item. As a result, all four images returned are the same.

<ul>
  <li *ngFor="let image of images | async">
    {{ image_thumbnail }}
  </li>
</ul>

UPDATE Image update based on @James Daniels response.

enter image description here


Solution

  • The main problem that you are facing is the async nature of getting the download URL. You can solve that with an Observable.fromPromise.

    getIssueImages() {
    
      this.albumsCollection = this.afs.collection<any>(/albums/${albumId}/images`);
      this.albums = this.albumsCollection.snapshotChanges().map(actions => {
      return actions.map(a => {
        const data = a.payload.doc.data();
        const id = a.payload.doc.id;
    
        // Firebase Reference
        var storage = firebase.storage();
    
        // Get the image storage reference
        var image = data.image_thumbnail;
    
        //Create an image reference to the storage location
        var imagePathReference = storage.ref().child(image);
    
        // Get the download URL and set the local variable to the result (url)
        var image_thumbnail = Observable.fromPromise(imagePathReference.getDownloadURL());
    
        return { id, image_thumbnail, ...data };
    
      });
    });
    

    }

    Now image_thumbnail is async.

    <ul>
      <li *ngFor="let image of images | async">
        {{ image.image_thumbnail | async }}
      </li>
    </ul>