2

I'm playing with Vue.js and trying to display a local image from a json file unsuccessfully.

Stories.vue

<template>
  <div class="container col-md-5">
    <div class="Library-title">
      <div class="app-name">Stories List</div>
    </div>
    <story-tyle v-for="story in stories" v-bind:story="story" :key="story.id"></story-tyle>
  </div>
</template>

<script>
import StoryTyle from '@/components/StoryTyle.vue'
import storyData from '@/assets/data/StoriesData.json'

export default {
  name: 'Stories',
  components: {
    StoryTyle
  },
  data () {
    return {
      stories: storyData
    }
  }
}
</script>

StoryTile.vue

<template>
  <div class="story-wrapper col-6">
    <div class="story-cover">
      <div class="story-cover-img" v-bind:style="{ 'background-image': 'url(' + story.cover + ')' }" v-bind:alt="story.title">
        <a v-on:click="nextPath()">
          <div class="story-details cover-select">
            <span v-if="story.frequency" class="story-frequency resize">{{ story.frequency }}</span>
            <div class="story-title resize">{{ story.title }}</div>
            <div class="story-author resize">{{ story.author }}</div>
          </div>
        </a>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  import: require('../assets/js/resize.js'),
  props: ['story'],
  name: 'story-tyle',
  methods: {
    nextPath () {
      if (this.story.frequency) {
        this.$router.push({name: 'Episodes'})
      } else {
        this.$router.push({name: 'Read'})
      }
    }
  }
}
</script>

StoriesData.json

[
  {
    "id": 1,
    "title": "Example of story title",
    "author": "Author Name",
    "cover": "../assets/img/covers/Blue-border-cover.png",
    "frequency": "weekly"
  },
  {
  ...
  }
]

The other data display correctly, but not the cover image. I've looked for different solutions but nothing seems to work. Images loads correctly if I get the data directly in the script of Stories.vue like this:

data () {
    return {
      stories: [
        {
          ...
          cover: require('../assets/img/covers/Blue-border-cover.png')
        },

And this is the relevant folder structure:

src
├─ assets
│   ├─ data
│   │   └─ StoriesData.json
│   └─ img
│       └─ covers
│           └─ Blue-border-cover.png
├─ components
│   └─ EpisodeTyle.vue
└─ views
    └─ Episodes.vue

what am I doing wrong?

9
  • 1
    the url() function accepts path relative to its location. can you share your folder structure? Commented Feb 16, 2019 at 22:37
  • 1
    Possible duplicate of Vue.js dynamic images not working Commented Feb 16, 2019 at 22:57
  • @Sumurai8, you link doesn't solve the issue. My problem is when I put the path into json file. Commented Feb 17, 2019 at 7:49
  • i meant - can you show the directory tree? Commented Feb 17, 2019 at 7:55
  • @Efrat I have added the folder structure now to the question. Commented Feb 17, 2019 at 8:28

2 Answers 2

1

Try to do it this way:

const images = require.context('@/assets/img/covers', false, /\.png$|\.jpg$/)

export default {
  ...
  methods: {
    loadImg(imgPath) {
      return images('./' + imgPath)
    },
    ...
  }

}

In your template:

<div class="story-cover-img"
     :style="`background-image: url(${loadImg(story.cover)})`"
     :alt="story.title"></div>

In .json

[
  {
    "id": 1,
    "title": "Example of story title",
    "author": "Author Name",
    "cover": "Blue-border-cover.png", // only name of a file
    "frequency": "weekly"
  },
  {
  ...
  }
]

Let me know if it worked.


Another idea: .json

[
  {
    "id": 1,
    "title": "Example of story title",
    "author": "Author Name",
    "cover": "url(\'/assets/img/covers/Blue-border-cover.png\')", // set bg url here
    "frequency": "weekly"
  },
  {
  ...
  }
]

And then in your template:

<div class="story-cover-img"
     :style="`background-image: ${story.cover}`"
     :alt="story.title"></div>

Let me know if that worked 😃

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

6 Comments

It did't work and no other content from json was displayed this time. I think the problem is on ${loadImg(story.cover)}. Tried also loadImg(story.cover) with same result. NOTE i've placed the const and the methods in Stories.vue where I return the json data.
You probably need to modify the paths in your json file to only include the filename. After all, the context already includes the entire path. Sadly codesandbox does not support require.context, so I can't create an example there.
Oh yeah, I forgot. @Sumurai8 is right. Since you are giving the path in the require images you only need to put a name of a file in a .json file ;-)
regarding the name of the file, I've done that but it still doesn't work. I am trying to put a codepen up, will post soon.
@AdamOrlov, thanks to your input I have found a very simple solution that worked. I have posted it as an answer.
|
1

After the input received in here, I played around with different solution and found a very simple solution that worked.

The problem is that images need to use require. So in StoryTile.vue I replaced:

v-bind:style="{ 'background-image': 'url(' + story.cover + ')' }"

with:

v-bind:style="{ 'background-image': 'url(' + require('../assets/img/covers/' + story.cover) + ')' }"

also in the json file, "cover": "Blue-border-cover.png" and not the entire path which is now expresses in StoryTile.vue.

and this did the trick!

1 Comment

Thanks for posting the followup - using require() in v-bind fixed the same issue I was having.

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.