17

I am trying to display an image with the img tag by using a path from props for the src attribute.

I've tried changing the path with @, using the whole path with src, adding ../assets/ in the component and only passing the file name (orange.png) as props. I always get the default broken image displayed. When inspecting in the browser, the path seems fine. When I display the image directly, I can see that the path is resolved to some different path <img data-v-1212d7a4="" src="/img/orange.7b71a54c.png">.


Edit: Additionally I tried this post Can't dynamically pass relative src path for imgs in Vue.js + webpack , where using <img :src="require(picture_src)" /> is given as an answer. This leads to an error: Error in render: "Error: Cannot find module '../assets/orange.png'"

(Edit2: This answer in the end worked for me in the end as described in my answer post.)
The same error occurs with the similar webpack method using let images = require.context('../assets/', false, /\.png$/) in my script part, as the answer on this post Can't dynamically pass relative src path for imgs in Vue.js + webpack .


I am new to Vue.js, so I don't exactly know what is happening or how to search for this or it might not have anything to do with what I'm originally trying.

I am able to display my image when I pass the path directly, like this

<img src="../assets/orange.png"/>

Now I'd actually like to pass it to my component in the props and then, inside the component, display it reading the path from props.

Component

<template>
  <div>
    <img :src=picture_src />
    <div class="pic_sub">{{pic_desc}}</div>
  </div>
</template>
<script>
export default {
  name: 'PictureCard',
  props: {
    picture_src: String,
    pic_desc: String
  }
}
</script>

Using the component:

<template>
  <div>
    <PictureCard pic_desc='some description text' picture_src='../assets/orange.png' />
  </div>
</template>

<script>
import PictureCard from './components/PictureCard.vue'
export default {
  name: 'app',
  components: {
    PictureCard
  }
}
</script>

If it is possible, I'd love to display my from a path that is passed through the component's props.

Otherwise I'd love to know some other solutions, work-arounds or knowledge on best practices in this case.

9
  • How about passing the image directly, instead of source string? For example import the image in your Main Component and pass it in PicutureCard? Commented Jun 17, 2019 at 4:51
  • This question comes up a lot. The easy fix is to use :src="require(picture_src)" Commented Jun 17, 2019 at 5:09
  • Possible duplicate of Vue.js - Trying to bind dynamic images... what should I do? and Vue.js dynamic images not working Commented Jun 17, 2019 at 5:11
  • Prob the best practice here is to create new Image with js and use url from props Commented Jun 17, 2019 at 8:34
  • Thank you for the feedback. When I try to use :src="require(picture_src)" I get an error and the whole component doesn't render anymore. Error in render: "Error: Cannot find module '../assets/orange.png'" Commented Jun 18, 2019 at 2:40

6 Answers 6

46

This worked for me

<img :src="require(`@/assets/img/${filename}`)">

where filename is passed in as a String prop e.g. "myImage.png".

Make sure you use the path specific to your project.

Source: https://github.com/vuejs-templates/webpack/issues/450

Note: @ is a webpack alias for /src that is set by default in Vue projects

Sign up to request clarification or add additional context in comments.

1 Comment

I get: 'ReferenceError: require is not defined' when running the Vue app in browser.
16

Newer solution:

The 'require()'-method does not work when using Vite.

I got this error: ReferenceError: require is not defined.


This is how I solved it without 'require()' and with composition API:

From parent component:

<ChildComponent icon-filename="icon.svg" />

ChildComponent:

<template>
  <div>
    <img :src="getImageUrl()">
  </div>
</template>

<script setup lang="ts">
import {defineProps} from "vue";

const props = defineProps({
  iconFilename: String
})

function getImageUrl() {
  // This path must be correct for your file
  return new URL(`../assets/icons/${props.iconFilename}`, import.meta.url)
}

</script>

2 Comments

Worked for me (nuxt3/vue3). But do you know what "import.meta.url" means ?
I think its a definition for formatting of the URL string. Docs here: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
5

After some research, I understand that my problem has to do with webpack and resolving filepaths. I used a modified version from this answer:
Vue.js dynamic images not working
and this answer:
Can't dynamically pass relative src path for imgs in Vue.js + webpack
Since the link in the second answer was dead, here's an active link to require.context documentation: https://webpack.js.org/guides/dependency-management/#requirecontext

My mistake when trying the second link's answer was that I returned only orange.png as the path, while I needed to add ./ at the beginning.

My working picture component now looks like this.

<template>
  <div>
    <img :src="resolve_img_url(picture_src)" />
    <div class="pic_sub">{{pic_desc}}</div>
  </div>
</template>
<script>
export default {
  name: 'PictureCard',
  props: {
    picture_src: String,
    pic_desc: String
  },
  methods: {
    resolve_img_url: function (path) {
      let images = require.context('../assets/', false, /\.png$|\.jpg$/)
      return images("./"+path)
    }
  }
}
</script>

I edited the regular expression to match .png and .jpg file endings. Therefore passing the prop looks like this now

<PictureCard  picture_src='orange.png' pic_desc='some picture description'/>

Comments

4

This works for me:

This is how i use my Componenent.

<image-element 
  :imageSource="require('@/assets/images/logo.svg')">
</image-element>

My Image Component:

<template>
  <div>
   ...
     <img v-bind:src=imageSource />
   ...
  </div>   
</template>

<script lang="ts">
 import Vue from 'vue'
 import { Component, Prop } from 'nuxt-property-decorator'

 @Component({
   components: {
    .....
   }
 })
 export default class extends Vue {
  ...
  @Prop({ default: '' }) imageSource!: String
  ...
 }
</script>

Comments

0

this is my favorite super simple way to do it. It can easily be reused in any file in any folder in my project. Just pass the actual path as a string from the perspective of the parent:

//some file
    <ParentA>
      <ImageComponent 
         myImagePath="../../../../../myCat.png"
      />
    </ParentA>

//some other file in a different folder in my project
    <ParentB>
      <ImageComponent 
         myImagePath="../../myCat.png"
      />
    </ParentB>


//child component file
<template functional>
   <div>
      <img :src="props.myImagePath">
   </div>
</template

Comments

0

Thats all not working for me :D

The template File is wrong! you need to add ":" before you set your prop.

thats how i should use the PictureCard

<PictureCard  :picture_src="require('orange.png')"
 pic_desc='some picture description'/>

and thats how my PictureCard should look like:

<template>
  <div>
    <img v-bind:src="picture_src" />
  </div>
</template>

export default class PictureCard extends Vue {

@Prop({ default: require("@/assets/orange.svg") }) img!: string
 }

so in case no prop is setted, so i added a default prop too. and yes i only used the image.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.