Reputation: 19
I am consuming data from a json file like this:
{"USD": {"7d": 32053.72, "30d": 33194.68, "24h": 31370.42}, "AUD": {"7d": 43134.11, "30d": 44219.00, "24h": 42701.11}, "RUB": {"7d": 2451451.45, "30d": 2465896.74, "24h": 2398589.80}, "JPY": {"7d": 3537735.55, "30d": 3664620.47, "24h": 3472632.46}, "BRL": {"7d": 167555.18, "30d": 169473.27, "24h": 163054.93}, "ILS": {"7d": 108658.72, "30d": 111663.67, "24h": 106988.58}, "GBP": {"7d": 23257.66, "30d": 23838.55, "24h": 22923.17}, "PLN": {"7d": 124869.61, "30d": 127872.57, "24h": 122668.16}, "CAD": {"7d": 40425.62, "30d": 41444.76, "24h": 39827.13}, "EUR": {"7d": 27187.74, "30d": 27955.81, "24h": 26659.79}}
And I am displaying it in a table. I calculate percentage change for 7 and 30 days and whether that percentage change is negative or positive. If the change is negative I want to color the text red, if it's positive I want to color it green, this is how I check if a change is positive or negative:
// Checking whether the change is positive or negative
if(item['7d'] > item['30d']) {
this.isPositive = true
} else if (item['7d'] < item['30d']) {
this.isNegative = true
}
So far my logic using a ternary operator does not work and I don't get my td's text colored red or green. Why and how can I achieve this? Here is my entire code:
<template>
<div>
<v-data-table
:headers="headers"
:items="bitcoinInfo"
:hide-default-footer="true"
class="primary"
>
<template #item.thirtyDaysDiff="{ item }">
<td :class="isPositive ? 'positive' : 'negative' ? isNegative : 'negative'">{{ calculateThirtyDayDifference(item) }}%</td>
</template>
<template #item.sevenDaysDifference="{ item }">
<td :class="isPositive ? 'positive' : 'negative' ? isNegative : 'negative'">{{ calculateThirtyDayDifference(item) }}%</td>
</template>
</v-data-table>
</div>
</template>
<script>
import axios from 'axios';
export default {
data () {
return {
bitcoinInfo: [],
isNegative: false,
isPositive: false,
headers: [
{
text: 'Currency',
align: 'start',
value: 'currency',
},
{ text: '30 Days Ago', value: '30d' },
{ text: '30 Day Diff %', value: 'thirtyDaysDiff'},
{ text: '7 Days Ago', value: '7d' },
{ text: '7 Day Diff %', value: 'sevenDaysDifference' },
{ text: '24 Hours Ago', value: '24h' },
],
}
},
methods: {
getBitcoinData() {
axios
.get('data.json')
.then((response => {
var convertedCollection = Object.keys(response.data).map(key => {
return {currency: key, thirtyDaysDiff: 0, sevenDaysDifference: 0, ...response.data[key]}
})
this.bitcoinInfo = convertedCollection
}))
.catch(err => console.log(err))
},
calculateThirtyDayDifference(item) {
let calculatedPercent = 100 * Math.abs((item['7d'] - item['30d']) / ((item['7d'] + item['30d']) / 2));
// Checking whether the change is positive or negative
if(item['7d'] > item['30d']) {
this.isPositive = true
} else if (item['7d'] < item['30d']) {
this.isNegative = true
}
return Math.max(Math.round(calculatedPercent * 10) / 10, 2.8).toFixed(2);
},
calculateSevenDayDifference(item) {
let calculatedPercent = 100 * Math.abs((item['24h'] - item['7d']) / ((item['24h'] + item['7d']) / 2));
return Math.max(Math.round(calculatedPercent * 10) / 10, 2.8).toFixed(2);
}
},
mounted() {
this.getBitcoinData()
}
}
</script>
<style>
.negative {
color: red;
}
.positive {
color: green;
}
</style>
Upvotes: 0
Views: 1221
Reputation: 37753
There are so many things wrong with your code I even don't know were to start...
You are using Conditional (ternary) operator in a wrong way. It has a form condition ? expression_for_true : expression_for_false
Method calculateThirtyDayDifference
is used in the template and at the same time it changes some of the data (isNegative
and isPositive
). NEVER do that! This causes infinite render loop.
In most cases you don't need to call any method
from the template - it is very inefficient as the template is rendered many times. Much better solution if you have some data and need to derive some more data (calculating something) is to use computed
and prepare all data you will need ahead of time
v-data-table
(docs) already renders <td>
so your code would render td
inside td
- use for example span
insteadconst data = JSON.parse('{"USD": {"7d": 32053.72, "30d": 33194.68, "24h": 31370.42}, "AUD": {"7d": 43134.11, "30d": 44219.00, "24h": 42701.11}, "RUB": {"7d": 2451451.45, "30d": 2465896.74, "24h": 2398589.80}, "JPY": {"7d": 3537735.55, "30d": 3664620.47, "24h": 3472632.46}, "BRL": {"7d": 167555.18, "30d": 169473.27, "24h": 163054.93}, "ILS": {"7d": 108658.72, "30d": 111663.67, "24h": 106988.58}, "GBP": {"7d": 23257.66, "30d": 23838.55, "24h": 22923.17}, "PLN": {"7d": 124869.61, "30d": 127872.57, "24h": 122668.16}, "CAD": {"7d": 40425.62, "30d": 41444.76, "24h": 39827.13}, "EUR": {"7d": 27187.74, "30d": 27955.81, "24h": 26659.79}}')
new Vue({
el: '#app',
vuetify: new Vuetify(),
template: `
<v-app>
<v-main>
<v-container>
<v-data-table :headers="headers" :items="rowsToDisplay" :hide-default-footer="true" class="elevation-1">
<template #item.thirtyDaysDiff="{ item }">
<span :class="item.thirtyDaysDiffClass">{{ item.thirtyDaysDiff }}%</span>
</template>
<template #item.sevenDaysDiff="{ item }">
<span :class="item.sevenDaysDiffClass">{{ item.sevenDaysDiff }}%</span>
</template>
</v-data-table>
</v-container>
</v-main>
</v-app>
`,
data() {
return {
bitcoinInfo: data,
headers: [{
text: 'Currency',
align: 'start',
value: 'currency',
},
{
text: '30 Days Ago',
value: '30d'
},
{
text: '30 Day Diff %',
value: 'thirtyDaysDiff'
},
{
text: '7 Days Ago',
value: '7d'
},
{
text: '7 Day Diff %',
value: 'sevenDaysDiff'
},
{
text: '24 Hours Ago',
value: '24h'
},
],
}
},
methods: {
calculateDifference(a, b) {
let calculatedPercent = 100 * Math.abs((a - b) / ((a + b) / 2));
return Math.max(Math.round(calculatedPercent * 10) / 10, 2.8).toFixed(2);
},
getDiffClass(a, b) {
return a > b ? 'positive' : a < b ? 'negative' : ''
}
},
computed: {
rowsToDisplay() {
return Object.keys(this.bitcoinInfo)
.map(key => {
return {
currency: key,
...data[key]
}
}).map((item) => ({
...item,
thirtyDaysDiff: this.calculateDifference(item['7d'], item['30d']),
thirtyDaysDiffClass: this.getDiffClass(item['7d'], item['30d']),
sevenDaysDiff: this.calculateDifference(item['24h'], item['7d']),
sevenDaysDiffClass: this.getDiffClass(item['24h'], item['7d']),
}))
}
}
})
.negative {
color: red;
}
.positive {
color: green;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.14/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.js"></script>
<div id="app">
</div>
Upvotes: 1