I am stuck on a task given to me on Vue JS and don't know what's going wrong on this code.
The task is generating dynamic table with 5 columns background color with 4 colors i.e red, blue, yellow, green. When the loop of column comes to 5th column then background color of red should be placed on it and next row continues with the blue, yellow, green, red again.
new Vue({
el: '#app',
data: {
tableRows: ['Table Row 1'],
counter: 1,
bgColor: ['red', 'blue', 'yellow', 'green'],
fontSize: '30',
colNumber: 0,
maxColumn: 5,
},
computed: {
bgColorComputed: function() {
if (this.colNumber == 4) {
this.colNumber = 0;
return this.bgColor[this.colNumber];
}
return this.bgColor[this.colNumber];
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<table border="1" width="500px" height="300px">
<tr v-for="(content, index) in tableRows">
<td v-for="colorIndex in maxColumn" :style="{ backgroundColor: bgColorComputed }">
bgColorComputed : {{ bgColorComputed }} <br> <br>
row count {{ counter }} <br>
column count {{ colNumber = colorIndex - 1 }}
</td>
</tr>
</table>
</div>
The output of this code is : Red,Red,Blue,Yellow,Green instead of Red,Blue,Yellow,Green,Red.
Why red is coming two times while the returning computedBgColor are red,blue,yellow,green?
Computed properties are cached. You are trying to use a single bgColorComputed
property to represent lots of different colors at the same time. This is not how it is intended to be used.
Instead you could move your code into a method, and then call the method multiple times (once for each column).
Additional problems:
The way you were tracking your indexes was unreliable.
Instead of checking for if (this.colNumber == 4)
as a special case, it is better to use the mod operator this.bgColor[colorIndex % this.bgColor.length]
. This will work for any column not just 4.
Your initial column index was set to zero. Then later you update it using v-for="colorIndex in maxColumn"
(which starts at 1) then {{ colNumber = colorIndex - 1 }}
which sets the colNumber back to zero again. This is why you were getting two red columns. It is just unnecessary. Ideally you should avoid mutating state inside your view template so you don't run into these inconsistency issues.
new Vue({
el: '#app',
data: {
tableRows: ['Table Row 1'],
counter: 1,
bgColor: ['green', 'red', 'blue', 'yellow',],
fontSize: '30',
colNumber: 0,
maxColumn: 5,
},
methods: {
getBgColor: function(colorIndex) {
return this.bgColor[colorIndex % this.bgColor.length];
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<table border="1" width="500px" height="300px">
<tr v-for="(content, index) in tableRows">
<td v-for="colorIndex in maxColumn"
:style="{ backgroundColor: getBgColor(colorIndex) }">
getBgColor : {{ getBgColor(colorIndex) }} <br> <br>
row count {{ counter }} <br>
column count {{ colNumber = colorIndex - 1 }}
</td>
</tr>
</table>
</div>