How to do a fallback img in v-img in Vuetify?

Viewed 9960

In Vuetify I have a v-img, and I want to change the image to a fallback one if the main one fails.

<v-img :src="cPicture" contain v-on:error="onImgError"></v-img>


cPicture : function() {
            return this.failed_image ? "https://assets.dryicons.com/uploads/icon/svg/9872/ab3c0a16-6f14-4817-a30b-443273de911d.svg" : "http://myimg.jpg/";
        },


onImgError : function(event) {
            alert(1);
            this.failed_image = true;
            //this.$forceUpdate();
        },

the alert 1 happens. Vuetify also throws an error in the console. But the fallback image does not show.

How can I fix this?

The main image above has intentionally a bad link, but if I use a good link, it will be shown.

4 Answers

You could use cPicture as a computed property and onImgError as a method :

new Vue({
  el: '#app',
  data() {
    return {
      failed_image: false
    }
  },
  computed: {
    cPicture: function() {
      return this.failed_image ? "https://picsum.photos/500/300?image=4" : "https://pisum.photos/500/300?image=5";
    },



  },
  methods: {
    onImgError: function(event) {

      this.failed_image = true;

    }
  }
})
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@1.3.7/dist/vuetify.min.js"></script>

<div id="app">
  <v-app id="inspire">
    <v-layout>
      <v-flex xs12 sm6 offset-sm3>
        <v-card>
          <v-container grid-list-sm fluid>
            <v-img :src="cPicture" contain v-on:error="onImgError"></v-img>
          </v-container>
        </v-card>
      </v-flex>
    </v-layout>
  </v-app>
</div>

check this pen

EDIT

I had provided an invalid image link for the desired image, in this case we will have an exception which will be shown in console :

"[Vuetify] Image load failed

in this case we will load another image with a valid link

I do the same thing, but with less code.

<v-img tile :src="logo.url" v-on:error="logo.url='/logo.svg'" />

This has been asked on github and should be added in Vuetify 3

Here is my way of solving this in the meantime

I first create two data

data(): {
 avatarLoadingFailed: false,
 fallbackAvatar: fallbackAvatar,
}

fallbackAvatar is the image file I want to display in case of loading failure

Then I create a computed to hold the avatar to be displayed

computed: {
  avatar() {
    return this.avatarLoadingFailed
      ? this.fallbackAvatar
      : this.getUserAvatar;
  },
}

Finally in my template tag

// @error="avatarLoadingFailed = true" works fine as well
<v-img :src="avatar" v-on:error="avatarLoadingFailed = true"/>

I have tried and tested this in VueJS with and without typescript

I like what @maurilio-atila did. In my case image was coming from another server and I ended up doing this:

 <v-img :src="`${item.image ?`https://some/endpoint/${item.image}` : '/fallback.png'}`"/>

While it doesn't handle v-on:error, it avoids it.

Related