Mark Simonson
Mark Simonson

Reputation: 71

vue.js vuefire firebase storage image url

I'm new to Vue and Firebase. In VueJS, I am trying to replicate the Firebase friendlychat function that returns the proper image URL for an image stored in Firebase storage ( FriendlyChat.prototype.setImageUrl). I have this function defined in a vue component:

let messagesRef = fbdb.ref('messages')
export default{
  firebase: {
    messages: messagesRef.limitToLast(20)
  },    
  methods: {
    getImageUrl: function (imageUri) {
  // If the image is a Firebase Storage URI we fetch the URL.
  if (imageUri) {
    this.showImage = true
    if (imageUri.startsWith('gs://')) {
      // var loadingimg = LOADING_IMAGE_URL // Display a loading image first.
      fbstorage.refFromURL(imageUri).getMetadata().then(function (metadata) {
        let img = metadata.downloadURLs[0]
        console.log('firbase image url', img)
        return img
      })
    }
    else {
      return imageUri
    }
  }
  else {
    this.showImage = false
    return ''
  }
} <...>

And in the HTML template, if I simply try to call the function, it doesn't work.

<div v-for ="message in messages">
  <img :src="getImageUrl(message.imageUrl)">
 ...
</div>

I can't figure out the correct way in Vue to get the results of this function (because it is a promise?) Any help is appreciated!

Upvotes: 2

Views: 2631

Answers (1)

Mark Simonson
Mark Simonson

Reputation: 71

I found a method in Vue to return the URL for a Firebase Storage URI using a computed variable that sets a data property, with the help of vue-async-computed. While it works, it is clearly not the proper way to handle the situation and input on a better way is appreciated.

Because the firebase function is a promise, you can't simply request the result of a computed variable. I don't yet know how to deal with this properly, although the vue-async-computed seems to simplify it a little.

In a variation from the original code I submitted, I created a component for a single message (which simplifies things a bit). The component gets the data from a props value - simple enough in VueJS. In this case, message.imageURL contains the Firebase storage URI and we need a way to convert it to the actual URL.

HTML template - :src references the data value imageURL.

<img :src="imageURL">

Component JavaScript code:

The computed function, fbImage, calls the Firebase promise to get the URL and then sets the data value called imageURL. This doesn't work, however, without the asyncComputed function, which seems to handle promise (return the result after the promise is resolved).

I thought at first I need to reference the computed function in the HTML binding, e.g., , but this doesn't work.

props: ['message'],
 data: function () {
  return {
   imgURL: '' // gets populated when fbImage is computed
   }
  },
computed: {
fbImage: function () {
  // If the image is a Firebase Storage URI we fetch the URL.
  var _this = this
  var _imageURL = this.message.imageUrl
  if (_imageURL) {
    if (_imageURL.startsWith('gs://')) {
      fbstorage.refFromURL(_imageURL).getMetadata().then(function (metadata)      {
        _this.imgURL = metadata.downloadURLs[0]  // imgURL is component data
      })
    }
    else {
      return _imageURL
    }
  }
  else {
    return ''
   }
},
asyncComputed: {
 img () {
   return new Promise(resolve =>
     this.fbImage
 )
}

Upvotes: 1

Related Questions