1

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 class="item drag" :key="element" :style="[{ 'border-top-color': 'brdrTpClr' }]">
            {{ element.title }}
            <div class="addico" :key="index">
              <i class="fas fa-add"@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.

2 Answers 2

1

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": '#00A3A1',
  "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.

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

1 Comment

Thanks! I had no idea how to do that, your help was precious!
0

I would make a method called getBorderColor(item) which returns the colour based on the group, and then dynamically bind it using Vue.

<div 
  class="item drag" 
  :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`;
}

1 Comment

If you place the colors in data, you're making them reactive(e.g: Vue wraps them in functions which are triggered whenever their values change). That's completely unnecessary, since the colors are not changing so it would make a lot more sense to place them outside the component. The other benefit is that, if you have a thousand instances of this component, the colors const gets created only once (if placed outside), whereas in your suggestion it gets created for each instance (and each of them is made reactive). In web, performance matters.

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.