foka135
foka135

Reputation: 187

Vue computed is not working properly and is always false

I was just trying to add a class if the number is greater than 0 and add a other class if it is less than 0.

Here is my code:

var prices = new Vue({
  el: "#prices",
  data: {
    message: "Hello Vue!",
    currencies: [],
  },
  computed: {
    color() {
      return this.price_change_percentage_1h_in_currency > 0 ? "inc" : "dec";
    }
  },
  // Getting the Data DO NOT TOUCH! :)
  mounted: function() {
    axios.get("https://api.coingecko.com/api/v3/coins/markets?vs_currency=eur&order=market_cap_desc&per_page=100&page=1&sparkline=false&price_change_percentage=1h%2C%2024h%2C7d")
      .then(response => {
        this.currencies = response.data;
        console.log(response);
      })
      .catch(error => {
        console.log(error);
      });
  },
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<table id="prices">
  <tbody>
    <tr v-for="currency, index in currencies">
      <td v-html="index + 1"></td>
      <td :class="color">{{currency.price_change_percentage_1h_in_currency.toFixed(2)}}%</td>
      <td :class="color">{{currency.price_change_percentage_24h.toFixed(2)}}%</td>
      <td :class="color">{{currency.price_change_percentage_7d_in_currency.toFixed(2)}}%</td>
  </tbody>
</table>

As you can see I am doing it with computed: color(). Everything is working but it always adds the class "dec" to the tabledata, even though it is greater than 0.

Please end my suffering with helping me.

Thanks.

Upvotes: 2

Views: 569

Answers (4)

Kevin Li
Kevin Li

Reputation: 150

What do you mean this.price_change_percentage_1h_in_currency ?

In my opinion, you should make computed functions like this.

<td :class="color(currency.price_change_percentage_1h_in_currency)"></td>

methods() {
   color (currency) {
      return currency > 0 ? "inc" : "dec";
   }  
}

Upvotes: 3

ibrahim mahrir
ibrahim mahrir

Reputation: 31692

That's because the color property is defined on the component itself and not on each currency object. All the generated tds will refer to the same color property which is calculated using the property price_change_percentage_1h_in_currency on the component which is undefined because the component doesn't have one.

Either add the color property to the currency objects when they're fetched:

  .then(response => {
    response.data.forEach(item =>
      item.color = item.price_change_percentage_1h_in_currency > 0 ? "inc" : "dec"
    );
    this.currencies = response.data;
  })

Or, better yet, compute the class in the template, add it to tr so you don't have to repeat it for each of the child tds:

<tr v-for="currency, index in currencies" :class='[ currency.price_change_percentage_1h_in_currency > 0 ? "inc" : "dec" ]'>

demo:

var prices = new Vue({
  el: "#prices",
  data: {
    message: "Hello Vue!",
    currencies: [],
  },
  computed: {
    color() {
      return this.price_change_percentage_1h_in_currency > 0 ? "inc" : "dec";
    }
  },
  // Getting the Data DO NOT TOUCH! :)
  mounted: function() {
    axios.get("https://api.coingecko.com/api/v3/coins/markets?vs_currency=eur&order=market_cap_desc&per_page=100&page=1&sparkline=false&price_change_percentage=1h%2C%2024h%2C7d")
      .then(response => {
        this.currencies = response.data;
      })
      .catch(error => {
        console.log(error);
      });
  },
})
.dec {
  background-color: #ffaaaa;
}

.inc {
  background-color:#aaffaa;
}

.as-console-wrapper {
  height: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<table id="prices">
  <tbody>
    <tr v-for="currency, index in currencies" :class='[ currency.price_change_percentage_1h_in_currency > 0 ? "inc" : "dec" ]'>
      <td v-html="index + 1"></td>
      <td>{{currency.price_change_percentage_1h_in_currency.toFixed(2)}}%</td>
      <td>{{currency.price_change_percentage_24h.toFixed(2)}}%</td>
      <td>{{currency.price_change_percentage_7d_in_currency.toFixed(2)}}%</td>
  </tbody>
</table>

Upvotes: 0

bitDaft
bitDaft

Reputation: 177

In your computed function you are referencing the variable this.price_change_percentage_1h_in_currency, but this variable is neither defined in the data nor is it obtained through props.
So the default value of that will be undefined.

Looking at the HTML part I'm assuming that price_change_percentage_1h_in_currency is part of the object obtained in the response list data from the API.

So what you can do is to compute the data in the then part of the API call.

mounted: function() {
    axios.get("https://api.coingecko.com/api/v3/coins/markets?vs_currency=eur&order=market_cap_desc&per_page=100&page=1&sparkline=false&price_change_percentage=1h%2C%2024h%2C7d")
      .then(response => {
        this.currencies = response.data;
        this.currencies.forEach(currency => {
          currency['color'] = currency.price_change_percentage_1h_in_currency > 0 ? "inc" : "dec";
        })
        console.log(response);
      })
      .catch(error => {
        console.log(error);
      });
  },

and then in html use it like so

<td :class="currency.color">{{currency.price_change_percentage_1h_in_currency.toFixed(2)}}%</td>

Upvotes: 1

Vagan M.
Vagan M.

Reputation: 463

You don't have this param in your data this.price_change_percentage_1h_in_currency

You need to use something like this

methods: {
    color(price) {
      return price > 0 ? "inc" : "dec";
    }
  }

and send price from template

Upvotes: 2

Related Questions