I have a JSON list of items that I import in my vue component, I loop though that file in order to show them. Each item belong to a specific 'group' :
See IMG
E.g. :
{
"type": "Simple list",
"title": "Simple list",
"id": 1,
"group": "list-component",
"properties": "lorem lipsum"
},
I would like to apply a CSS 'border-top-color' to each item according to its group.
I was trying to apply the conditions when mouted(){} but I'm not sure if I'm doing it right. Here's my atempt :
The template (I'm using VueDraggable, don't mind it) :
<div :key="element" :style="[{ 'border-top-color': 'brdrTpClr' }]">
{{ element.title }}
<div :key="index">
<i @click="$emit('pushNewElt', element.id)"></i>
</div>
</div>
The script :
data() {
return {
dragItems: dragItemsList,
brdrTpClr: "",
};
},
mounted() {
for (let i = 0; i <= 15; i ) {
if (this.dragItems[i].group == "list-component") {
// I'm not sure how to do it
// the color I want to apply : #00A3A1b
} else if (this.dragItems[i].group == "location-media-component") {
// #005EB8
} else if (this.dragItems[i].group == "container-component") {
// #0091DA
} else if (this.dragItems[i].group == "UI-component") {
// #6D2077
} else if (this.dragItems[i].group == "reader-scanner-component") {
// #470A68
}
}
},
I'm using i<=15 instead of i<=this.dragItems.length because of a bug, don't mind it too.
CodePudding user response:
You can map colors and use method to apply them:
const app = Vue.createApp({
data() {
return {
dragItems: [{"type": "Simple list", "title": "Simple list", "id": 1, "group": "list-component", "properties": "lorem lipsum"}, {"type": "other", "title": "other", "id": 2, "group": "UI-component", "properties": "lorem lipsum"}, {"type": "other", "title": "other", "id": 3, "group": "container-component", "properties": "lorem lipsum"}],
mapColors: [{id: 'list-component', color: '#00A3A1'}, {id: 'location-media-component', color: '#005EB8'}, {id: 'container-component', color: '#0091DA'}, {id: 'UI-component', color: '#6D2077'}, {id: 'reader-scanner-component', color: '#470A68'}]
};
},
methods: {
brdrTpClr(group) {
return this.mapColors.find(c => c.id === group).color
}
},
})
app.mount('#demo')
.item {
border: 2px solid transparent;
}
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<div id="demo">
<div v-for="element in dragItems">
<div :key="element" :style="`border-top-color: ${brdrTpClr(element.group)}`">
{{ element.title }}
<div :key="index">
<i @click="$emit('pushNewElt', element.id)"></i>
</div>
</div>
</div>
</div>
CodePudding user response:
I would make a method called getBorderColor(item)
which returns the colour based on the group, and then dynamically bind it using Vue.
<div
:style="[{ 'border-top-color': getBorderColor(element) }]"
>
{{ element.title }}
// Add icon etc.
</div>
getBorderColor(element) {
// Can use a switch statement, but here's a simple ternary if/else as an example
return element.group === "list-component" ? `#00A3A1b`
: element.group === "location-media-component" ? `#005EB8`
: element.group === "container-component" ? `#0091DA`
: element.group === "UI-component" ? `#6D2077`
: element.group === "reader-scanner-component" ? `#470A68`
: `#000000`; // Default colour
}
or for a cleaner option you can have an object with your groups as keys and colours as values in data
e.g.
return {
dragItems: dragItemsList,
brdrTpClr: "",
colors: {
"list-component": `#00A3A1b`,
"location-media-component": `#005EB8`,
// etc.
},
};
getBorderColor(element) {
return this.colors[element.group] || `#000`;
}
CodePudding user response:
Probably the most efficient (performance wise) and the most readable solution would be to declare a constant colorMap, outside the component, and then return the correct value or a fallback, using a method:
<script>
const colorMap = {
"list-component": '#00A3A1b',
"location-media-component": '#005EB8',
"container-component": '#0091DA',
"UI-component": '#6D2077',
"reader-scanner-component": '#470A68'
}
export default {
//...
methods: {
borderColor(group) {
return colorMap[group] || '#000'
}
}
}
</script>
<template>
...
<div :style="{borderColor: borderColor(element.group)}">
content...
</div>
</template>
As a general rule, you want to take anything more complicated than a simple ternary outside of the template and provide it via either computed
or methods
.
Side note: the above method can also be written as computed
:
computed: {
borderColor: group => colorMap[group] || '#000'
}
If you find yourself needing the colorMap
in more than one component, export it from a constants.(js|ts)
file and import everywhere needed. I typically name that file helpers
, as it typically also contains static functions or maps (anything I reuse across multiple components/modules).
Important: you're currently passing an array to :style
. You should be passing an object.