Vue.js dynamic images not working

186,361

Solution 1

I got this working by following code

  getImgUrl(pet) {
    var images = require.context('../assets/', false, /\.png$/)
    return images('./' + pet + ".png")
  }

and in HTML:

<div class="col-lg-2" v-for="pic in pics">
   <img :src="getImgUrl(pic)" v-bind:alt="pic">
</div>

But not sure why my earlier approach did not work.

Solution 2

Here is a shorthand that webpack will use so you don't have to use require.context.

HTML:

<div class="col-lg-2" v-for="pic in pics">
    <img :src="getImgUrl(pic)" v-bind:alt="pic">
</div>

Vue Method:

getImgUrl(pic) {
    return require('../assets/'+pic)
}

And I find that the first 2 paragraphs in here explain why this works? well.

Please note that it's a good idea to put your pet pictures inside a subdirectory, instead of lobbing it in with all your other image assets. Like so: ./assets/pets/

Solution 3

You can try the require function. like this:

<img :src="require(`@/xxx/${name}.png`)" alt class="icon" />

The @ symbol points to the src directory.

source: Vue URL transfrom rules

Solution 4

There is another way of doing it by adding your image files to public folder instead of assets and access those as static images.

<img :src="'/img/' + pic + '.png'" v-bind:alt="pic" >

This is where you need to put your static images:

enter image description here

Solution 5

Your best bet is to just use a simple method to build the correct string for the image at the given index:

methods: {
  getPic(index) {
    return '../assets/' + this.pics[index] + '.png';
  }
}

then do the following inside your v-for:

<div class="col-lg-2" v-for="(pic, index) in pics">
   <img :src="getPic(index)" v-bind:alt="pic">
</div>

Here's the JSFiddle (obviously the images don't show, so I've put the image src next to the image):

https://jsfiddle.net/q2rzssxr/

Share:
186,361
Saurabh
Author by

Saurabh

Writing little good, some bad and mostly ugly code for last 5 years in C, Ruby, Angular, Node, Vue.js, java, scala and recently exploring Big data tools like apache-storm, apache-spark, akka, etc. Trying to help people whenever possible and making this earth more liveable place one bit at a time.

Updated on July 08, 2022

Comments

  • Saurabh
    Saurabh almost 2 years

    I have a case where in my Vue.js with webpack web app, I need to display dynamic images. I want to show img where file name of images are stored in a variable. That variable is a computed property which is returning a Vuex store variable, which is being populated asynchronously on beforeMount.

    <div class="col-lg-2" v-for="pic in pics">
       <img v-bind:src="'../assets/' + pic + '.png'" v-bind:alt="pic">
    </div>
    

    However it works perfectly when I just do:

    <img src="../assets/dog.png" alt="dog">
    

    My case is similar to this fiddle, but here it works with img URL, but in mine with actual file paths, it does not work.

    What should be correct way to do it?

    • Mohamed Raza
      Mohamed Raza over 3 years
      solved ` <v-img :src="require(@/assets/ + items.image)" height="200px"></v-img>` this one also solved the problem
  • craig_h
    craig_h over 7 years
    Really? Here's an example with real images which seems to work fine: jsfiddle.net/q2rzssxr/1
  • Saurabh
    Saurabh over 7 years
    Not sure why, I got it working by the code I have written in another answer. You example even works without this function, see here: jsfiddle.net/9a6Lg2vd/1
  • Saurabh
    Saurabh over 7 years
    In my case, pics is being populated asynchronously using Vuex store, may be that has something to do about it, I tried to simulate it, but did not work: jsfiddle.net/9a6Lg2vd/2
  • Saurabh
    Saurabh over 7 years
    My case is more like this one: jsfiddle.net/9a6Lg2vd/4 , but in my local pets gets data populated from an ajax call, but images don't get render.
  • Saurabh
    Saurabh over 7 years
    This also works: jsfiddle.net/9a6Lg2vd/5, not sure why it not working with file paths.
  • antoine
    antoine over 6 years
    According to nickmessing: "The expression inside v-bind is executed at runtime, webpack aliases at compile time." github.com/vuejs/vue-loader/issues/896
  • samlandfried
    samlandfried over 5 years
    @Grigio has a nice enhancement to this answer: stackoverflow.com/a/47480286/5948587
  • StefanBob
    StefanBob about 5 years
    This worked for me except for the alt tag I omitted the v-bind
  • drakkar
    drakkar about 5 years
    saved me a lot of pain, I got strange Error: Cannot find module './undefined' using require, thanks
  • estani
    estani over 4 years
    The problem was that the path doesn't exist. The whole vue app get compiled by webpack into a single script (and images are also renamed normally, using a hash of the contents). Using require.context, you force the files to be seen by webpack and resolve to the resulting image. Check the working link in the browser and you'll see what I mean. Great solution.
  • thinsoldier
    thinsoldier over 4 years
    What if I don't want my images to be in the assets folder? What if they only exist in the website's public folder because they are uploaded by users of the admin area?
  • harm
    harm over 4 years
    Why is that @ symbol required?
  • feng zhang
    feng zhang over 4 years
    @ symbol is not required, it offten represent your src dir when using Resolve | webpack (vue-cli is already config this.).
  • jukenduit
    jukenduit about 4 years
    I think this is the way to go, not the assets folder.
  • goodniceweb
    goodniceweb almost 4 years
    dynamic require didn't work for me too in the latest Vue2
  • Mohamed Raza
    Mohamed Raza over 3 years
    ` <v-img :src="require(@/assets/ + items.image)" height="200px"></v-img>` this one also solved the problem
  • lin
    lin over 3 years
    hello, I have tried this but failed, then I found another solution that using template literals. It could work and I want to share this: stackoverflow.com/questions/57349167/…
  • makkus
    makkus over 3 years
    This was the only working solution after a lot of trying..
  • Mohamed Raza
    Mohamed Raza over 3 years
    Thank you this works :src="require(../assets/category_avatar/baby_kids.jpeg)"
  • Just Alex
    Just Alex over 3 years
    Even after so much years, this solution still works ! Thank you friend, you saved my nerves.
  • Bhaskar
    Bhaskar about 3 years
    The secret to each and every answer here is that they have ../assets in the require method, check stackoverflow.com/questions/57349167/… for more details
  • nth-child
    nth-child over 2 years
    This is the only solution that worked for me
  • Ngọc Nguyễn
    Ngọc Nguyễn over 2 years
    Require didn't work for me in Vue3 too, but this is an amazing solution
  • Muneer Khan
    Muneer Khan almost 2 years
    @antoine the GitHub link is correct and verified it is working in my case it is working with the require keyword. :src="require('../assets/img/maintenance_page_concept.svg')"
  • Arslan Ameer
    Arslan Ameer almost 2 years
    It is working fine in my case