3

I want to dynamically change the background-image on a ccs class in an imported component How can I do that?

I have installed 'vue-range-slider' and have imported RangeSlider

The range-slider is set up the following way.

<template>
  <div id="slider_div" >

  <range-slider
      class="slider"
      min="0"
      max="100">
  </range-slider>

 </div>
</template>

<script>
import RangeSlider from 'vue-range-slider'
import 'vue-range-slider/dist/vue-range-slider.css';

export default {
  name: 'susScore',
  data: function() {
    return {
      emoji: "../assets/emoji_small.jpg",
    }
  },
  components: {
    RangeSlider
  }

</script>

<style >
#slider_div{
  margin-top: 95px;
  margin-left: 4%;
}

.slider{
  width:200px;
}

.range-slider-knob {
    background-image: url("../assets/emoji_small.jpg")
}

</style>

In this case I am sending a specific image but I want to send an image dynamically using the data option, emoji, in the component.

Question
How can I dynamically update the background-image in the imported .range-slider-knob class?

I tried using CSS variables in a previous question here on SO (Dynamically add image with css variable in vue) but got the reply that that wasn't possible

user12288003
  • 199
  • 1
  • 4
  • 14

2 Answers2

2

You can't use vm properties in <style> tag, but you can update emoji in data to:

emoji: require("../assets/emoji_small.jpg")

... and then pass it to any template element using:

<whatever :style={backgroundImage: `url(${emoji})`} />

A fully working example: codesanbox.

I combined require() with a computed changing loaded image based on slider value.

tao
  • 82,996
  • 16
  • 114
  • 150
  • Thanks. Sure I can use codesandbox but all the code in the component is in the question so I don't know what more I can add. Also how do you import 'vue-range-slider' and RangeSlider in codesandbox ? I tried adding the whatever div that you suggested but got (Syntax Error: SyntaxError: Unexpected token) when rendering. It seems that something is missing, or what can be the issue? Thanks – user12288003 Jun 18 '20 at 18:55
  • You import them the same way you import them in any node based environment. You install the package (look in left-bottom corner) and `import whatever from 'whatever'`. `` is not to be used literally. It was a figure of speech, saying you could use it on either `
    `s or ``s.
    – tao Jun 18 '20 at 18:56
  • I have created a sandbox at the following link "https://codesandbox.io/live/rkGNK", everything works but when I added the suggested "div /whatever" the I got the following error "./src/sandbox/eval/transpilers/vue/template-compiler/loader.js"/r.default@https://codesandbox.io/static/js/vue-template-compiler.545cbd06b.chunk.js:1:3115 – user12288003 Jun 18 '20 at 19:18
  • I understood that "whatever" was more of a placeholder but I am still unsure what I should import. I am guessing I should import something from 'vue-range-slider' but not sure exactly what? – user12288003 Jun 18 '20 at 19:27
  • @user, none of your codesandbox links seem to work... If I can't see it, I can't fix it. – tao Jun 19 '20 at 00:35
  • I have saved the data in the link again. Hopefully it works now. https://codesandbox.io/live/EY0ng Thanks – user12288003 Jun 19 '20 at 10:12
  • @user, you're creating live sessions. When you log out, they're terminated ([this is how they look for me, because you're no longer *live*](https://i.stack.imgur.com/l3wAZ.png)). You have to create a new sandbox and select Vue from the templates. Add whatever packages you want, modify the styles, etc... – tao Jun 19 '20 at 15:21
  • Hi, ok I am live now again. It seems to close automatically since I am never logging out. I thought I created a new sandbox with Vue but will try to look at it again. Sorry – user12288003 Jun 19 '20 at 16:15
  • 1
    https://codesandbox.io/s/empty-morning-pcoso?file=/src/components/HelloWorld.vue this is another sandbox link. Maybe it works better? – user12288003 Jun 19 '20 at 16:17
  • Thank you very much – user12288003 Jun 19 '20 at 19:09
  • Sorry one last question that arose when trying to compile. I am getting an error "require is not defined", I tried adding **require() => require** in computed above **emoji()** but then I just receive another "require is not defined". Is there anything else I need to add here? I tried the examples on the link you shared but still same problem. Thanks – user12288003 Jun 19 '20 at 19:36
  • 1
    @user, if you're getting this in your project, setting `"env": { "node": true }` in your `eslintrc.js` (or in `package.json > eslintConfig`) should do it. If it's in codesandbox, just place `/* global require */` at the top of the file (if it's a `.js` file) or at the top of the ` – tao Jun 19 '20 at 22:23
  • Thank you. Changing node to true solved the problem. Now it all works, thanks – user12288003 Jun 20 '20 at 08:12
0

In the RangeSlider.vue file, line 13 shows that the component includes a named slot 'knob'. Vue Slots let you pass html/vue content into the component.

You could pass in a simple div on which you can dynamically change it's background using a method like @tao suggested. Note that a name attribute is given to match the name of the slot you are trying to replace; however, the name shouldn't be required because it is the only slot within component you are using.

<range-slider
   class="slider"
   min="0"
   max="100">
   <div
      name="knob"
      :style={backgroundImage: url(emoji)}
   />
</range-slider>

This method also gives you more freedom in how the knob is presented and/or manipulated with JS.

tony19
  • 125,647
  • 18
  • 229
  • 307
  • Thanks. I tried adding the div that you suggested but when rendering something seems to be missing. For example I get the error "Syntax Error: SyntaxError: Unexpected token". Should there be any citation marks or similar in the div? It seems that something is missing or? – user12288003 Jun 18 '20 at 18:52
  • 1
    Unless you declare it in computed: `computed: { require: () => require }`, `require` is not defined in `vm` context, so you can't use it in template. Basically, it has to be a property of `this` to be usable in template. See [this answer](https://stackoverflow.com/a/60240938/1891677). – tao Jun 18 '20 at 19:03
  • Oh right... Well, the [Vue loader](https://vue-loader.vuejs.org/guide/asset-url.html#transform-rules) should take care of a plain path anyway. On an additional note, I tried playing with the vue-range-slider in a small sandbox on my machine. I followed the documentation on overriding styles, nothing changed... And no changes occurred when I used a custom knob slot. Maybe the component is broken... – Jackson Baker Ryan Jun 18 '20 at 21:09
  • Ok, thanks. Regarding overriding styles it seems to work since I can change the image of the knob if I for example input _background-image: url("../assets/emoji_small.jpg")_ in the range-slider-knob class as specified in the example. So I can change the image but it can't get it to work when using slots – user12288003 Jun 19 '20 at 13:07