Search code examples
vue.jsv-forcomputed-properties

Computed property or other way to change style depending on value inside v-for in Vue


I have component like this:

Vue.component('mcp-item', {
    template: '#mcp-item-template',
    data() {
        return {
            name: "MCP v2",
            version: "2.0",
            imei: 'XXXXXX XX XXXXXX X',
            relays: [
                { name : "REL1", state : 0 },
                { name : "REL2", state : 0 }
            ],
            inputs: [
                { name: "BP1", state: 0, color: "#CC0000" },
                { name: "BP2", state: 0, color: "#CC0000"  },
                { name: "BP3", state: 1, color: "#00CC00"  },
                { name: "BP4", state: 0, color: "#CC0000"  },
                { name: "BP5", state: 0, color: "#CC0000"  },
                { name: "BP6", state: 0, color: "#CC0000"  }
            ],
        }
    },
    methods: {
        reboot: function (event) { alert( this.imei) }
    }
})

And somewhere in compoment template:

<table>
    <thead>
        <tr>
            <th>Input</th>
            <th>State</th>
        </tr>
    </thead>
    <tbody v-for="input in inputs" :key="input.name">
        <tr>
            <td :style="{ 'color': input.color}">{{input.name}}</td>
            <td>{{input.state}}</td>
        </tr>
    </tbody>
</table>

As you can see, now I have dedicated color field in my object (which is element of inputs array in data):

JS:

{ name: "BP1", state: 0, color: "#CC0000" }

HTML:

<td :style="{ 'color': input.color}">{{input.name}}</td>

I want to get rid of this extra property, but I can't figure out how can I use computed property inside of v-for loop to make red color for state==0 and green for state==1.


Solution

  • Rather than creating a computed property or adding the logic into the template, I would create a method getColor(state) which looks like this:

    getColor(state) {
      let color = '';
      if (state === 0) {
        color = 'red';
      } else if (state === 1) {
        color = 'green';
      }
      return { color };
    }
    

    Or if the only values are 0 and 1 you could shorten this to something like:

    getColor(state) {
      const color = state === 0 ? 'red' : 'green';
      return { color };
    }
    

    then call it like this:

    <td :style="getColor(input.state)">{{input.name}}</td>