Search code examples
javascriptazurevue.jsvuejs2azure-storage

v-if Not work when the function return true or false [VueJs]


I am working on VueJs, And In my template section .. I defined a condition to check if the image URL exists or not.

template:

<div v-for="(sub, key) in Work.sub" :key="sub.id" >
  <span v-if="Image('https://XXXX.blob.core.windows.net/XXXX/XXXXX-' + key +'.png')" > 
     <b-img :src="'https://XXXX.blob.core.windows.net/XXXX/XXXXX-' + key +'.png'" />
  </span>
  <span v-else>
     <b-img :src="default_avatar"/> 
  </span>
</div>

In script:

Image: function(img_url)
{
   return axios({
      method: "GET",
      timeout: 3000,
      headers: {
        .......................
      },
      url: img_url
   })
   .then( function(response){
      this.ifImageExist = true;
      return this.ifImageExist;
   })
   .catch( function(error){
      this.ifImageExist = false;
      return this.ifImageExist;
   })
},

For default_avatar it is aleady definded in the data section and no problem with it.

My problem is when the Image function checks if the image URL exists or not. If it exists it provides the image in the given URL, but if it does not exist, the image will be blank!

For example:

when I run the code, I result will be like this:

enter image description here

But I want the first image to filled by default image, not show does not exist icon!

How to solve this problem?


Solution

  • Alternative solution: It looks like the only diff between the v-if and v-else is b-img's src, so an alternative would be to move the logic into JavaScript, mapping Work.sub into an array of image URLs that default to default_avatar only if the URL doesn't resolve.

    So your template would be:

    <template>
      <div v-for="(img, index) in images" :key="index">
        <b-img :src="img" />
      </div>
    </template
    

    You'd add a data property to hold the image URLs:

    data() {
      return {
        images: []
      }
    }
    

    And a watcher on Work.sub, which sets this.images:

    watch: {
      'Work.sub': {
        immediate: true,
        async handler(sub) {
          // For each image URL, attempt to fetch the image, and if it returns
          // data (image exists), collect the URL. Otherwise, default.
          this.images = await Promise.all(Object.keys(sub).map(async (key) => {
            const img = sub[key];
            if (!img) return this.default_avatar;
    
            const url = `//placekitten.com/${img}`;
            const { data } = await axios.get(url);
            return data ? url : this.default_avatar;
          }));
        }
      }
    }
    

    demo