Skip to main content
  1. Posts/

Loading dynamic images in a Vue Component

·541 words·3 mins
Joe Erickson
Author
Joe Erickson
Senior software developer specializing in web development, AI, and helping others learn to code.

When I first started using Vue, one thing I got continually wrong was how to load an image into a Vue component dynamically. At first, I found that using an absolute URL worked, but that was only useful if I was storing the images on a CDN or other external site. If I included the images in my project, as either lightweight icons or static images, then using an absolute URL, with hostname and all, didn’t really work. What about when I wanted to test some new images locally or on a dev server? Linking directly to the images in production just wasn’t going to cut it.

When researching this, the Vue CLI documentation for static assets was, frankly, a little less than helpful. They didn’t give a good example for what I was trying to do.

What I was building was a little form control to take credit card numbers. It consisted of a single file Vue component and looked something like this:

<template>
	<div class="form-group">
    <label>Credit Card Number</label>
    <input type="text" name="creditCardNumber" v-model="creditCardNumber"
           placeholder="1111111111111111">
    <img class="creditLogo" v-bind:src="creditCardLogoSrc">
  </div>
</template>

<script>
export default {
  name: 'credit-card-field',
  computed: {
    creditCardLogoSrc(vm) {
      if(vm.creditCardNumber.startsWith('4')) {
        // Return the Visa image
      } else if (vm.creditCardNumber.startsWith('5')) {
        // Return the Mastercard image
      } else if (vm.creditCardNumber.startsWith('6')) {
        // Return the Discover image
      } else {
        // Return the generic image
      }
    }
  },
  data() {
    return {
      creditCardNumber: ''
    }
  }
}
</script>

What I wanted to happen was, as the user is typing in their credit card number, I will look at it and swap out the img tag’s source to show the credit card type that they were entering. I had a Visa image, a Mastercard image and a Discover image as well as the image of a generic credit card if it didn’t match any of those. Since all Visas start with 4, all Mastercards start with 5, and all Discover cards start with 6, this would be a pretty easy check to do.

The logic ended up being the easy part. The hard part was loading the images. I had the images in the Vue CLI provided assets folder, but how do I load them in?

Looking at the documentation, there are a lot of “in templates, do this” and “only in templates!” kinds of things. But I wasn’t in a template. I was in the code part of my component.

After much research, I found the answer was to require() the images from the asset folder. Intuitive! 😒

So, when I need to use an image that is in the assets folder, I can require() the relative path to that image in my computed method:

creditCardLogoSrc(vm) {
  if(vm.creditCardNumber.startsWith('4')) {
    return require('../assets/visa.png');
  } else if (vm.creditCardNumber.startsWith('5')) {
    return require('../assets/mastercard.png');
  } else if (vm.creditCardNumber.startsWith('6')) {
    return require('../assets/discover.png');
  } else {
    return require('../assets/credit.png');
  }
}

One nice plus to doing it this way is, if the image is small enough, require() will return a dataurl instead of a URL path, which will save an extra call to the server and make the component a little more self contained.

So if you need to load images from inside a Vue CLI project’s assets folder from outside the template of your component, now you know how.

Related

Should you always use getters in Vuex?

·1166 words·6 mins
One of the questions that comes up time and again concerning Vuex is “Do I always use a getter when accessing data? Or can I directly access the raw state?” It’s one of those things you hear about that you should do, but no one seems to really explain why. And do you really need to create a getter for every single piece of data that you put in the store? Isn’t that just a bunch of unneeded boilerplate and duplication?

Understanding data flow in Vuex

·646 words·4 mins
If you’re like me, when you first ran into Vuex, you probably wondered “How the heck does this work?” It’s not immediately obvious how these types of state management systems work, especially if you come from an SQL background. And do I even need it? In fact, the Vuex documentation has a quote that sums it up pretty well:

Thank you for seeing my talk at JavaScript and Friends!

·145 words·1 min
Thank you so much for coming out and seeing my talk at the JavaScript and Friends conference (or the video later on). I wanted to give you some extra links to some of the things that I talked about.

Notes and Further Reading for Your Own Personal Bootcamp Talk

·3617 words·17 mins
Welcome to further reading and notes from the Your Own Personal Bootcamp talk. It was great seeing you all at PyOhio this year and I can’t wait to come back again. I hope that, if you were able to see the talk, you were able to pull something away from the talk and had as much fun watching it as I did giving it.