Reputation: 671
I am trying to dynamically style an element based on a pokemon's type (eg. fire gets a fire icon, fire/flying gets 1 fire 1 flying).
I tried to do it with a ternary operator and :style
but it got really long and messy, so I'd prefer not to. Currently, I have it set as a method, and pass in an array, which look like this:
types: ["water", "flying"] //or sometimes just one value eg: types: ['fire']
here is my method:
methods: {
typeStyle: function (types) {
const backgroundImageUrls = []
for (const i in types) {
backgroundImageUrls.push('url(../assets/' + types[i] + '.svg)')
}
console.log(backgroundImageUrls)
let backgroundPosition = 'center'
if (backgroundImageUrls.length > 1) {
backgroundPosition = 'left right'
}
return {
backgroundImage: backgroundImageUrls.join(','),
backgroundPosition
}
}
}
and this is the html template it is called in:
<li
class="card"
v-for="(mon, index) in team"
:key="index"
>
<div class="cardfront-images"
:style="typeStyle(mon.types)"
>
...
</li>
but it's not working. I would also like to apply a 2nd effect, background-position
and do background-position: "center"
if there is 1 type, and background-position: "left right"
if there are two. but I get an error because of the hyphen in the CSS property.
So I have it working to where it makes a url()
for the background image (yay!), but unfortunately styling is not applied. So something isn't working, obviously. I have also updated my codeblocks to reflect changes.
EDIT2: So this solution did work, and I have given the check. For some reason, it didn't like my local assets being string-literaled in, so I just called the images from my git repo. Which I guess is good enough since I'm really just making this for my own education.
Upvotes: 0
Views: 797
Reputation: 66103
What you can do is to store all the background URLs into an array, and then join the array before the return
statement.
With regards to the background-position
property, remember that in JS all CSS properties are kebab cased, because -
will cause JS to interpret it as an arithmetic operation, so using backgroundImage
should be the way to do it.
Assuming that the url
key in each object in the types
array of object contains the actual path to the image, you can do this. Note that you should really avoid using arrow functions when defining a Vue method, because the this
in the function will no longer refer to the component instance.
new Vue({
el: '#app',
data: function() {
return {
team: [{
ability: "Keen Eye",
name: "Wingull",
id: 278,
types: [{
type: {
name: "water",
url: "http://via.placeholder.com/100x100?text=water"
},
},
{
type: {
name: "flying",
url: "http://via.placeholder.com/100x100?text=flying"
}
}
]
}]
};
},
methods: {
typeStyle: function(types) {
// Collect all URLs into an array with the template literal applied so we can use it directly in CSS
const backgroundImageUrls = types.map(entry => `url(${entry.type.url})`);
// Default value of background-position
let backgroundPosition = 'center';
if (backgroundImageUrls.length > 1) {
// Example: you want one image on the top left, and another on the top right
backgroundPosition = 'top left, top right';
}
return {
backgroundImage: backgroundImageUrls.join(','),
backgroundPosition
};
}
}
});
.cardfront-images {
width: 500px;
height: 100px;
background-repeat: no-repeat;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li class="card" v-for="(mon, index) in team" :key="index">
{{ mon.ability }}, {{ mon.name }}, {{ mon.id }}
<div class="cardfront-images" :style="typeStyle(mon.types)"></div>
</li>
</ul>
</div>
Upvotes: 1
Reputation: 378
There are a few different ways you can do this:
For conditional styling you can use dynamic classes like:
<div :class="{ mon.type }"
This will then automatically take the type name ('fire', 'water', etc.) on which you can use CSS if you'd like.
For rendering the icons properly, you will need to make some adjustments to the JSON object you give it.
But for that I would need to know whether you have all the information available or otherwise in what format you will fetch it.
I will update my answer when you let me know.
Upvotes: 1