1

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

MegaTron
  • 3,133
  • 6
  • 28
  • 45

1 Answers1

1

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>
James Daniels
  • 6,883
  • 4
  • 24
  • 28
  • Hi James! Thank you very much for the response. I included 'import 'rxjs/add/observable/fromPromise';' in my imports. Do I need to do anything else in regards to 'fromPromise'? The HTML shows a list of four urls (correct), but they are the reference URLs, not the download URLs. I also had to remove the 'asyn' pipe from the html. However, I've updated the question with an image if I do 'console.log('image_thumbnail') This might help? Anyway thoughts? Thanks again. – MegaTron Oct 16 '17 at 07:51
  • Actually, by just changing image_thumbnail to a new variable name, such as 'newImageURL', it worked! - I think image_thumbnail was still referencing the original storage reference node name. Thank you James! :) – MegaTron Oct 16 '17 at 08:02