[Vuejs]-Vue.js Getting erros even if component is not rendered

1👍

Edit (after seeing the actual error):

The problem is you’re trying to use .toFixed on something that is not a number. To guard against it, you have to wrap the value in Number.

Number(item.daily_total || 0).toFixed(6)

Also, your item.daily-total template slot can be significantly simplified as:

<template v-slot:item.daily_total="{ value }">
  <span :class="{ 'error--text': value < 0, 'success--text': value > 0 }"
        v-text="Number(value || 0).toFixed(6)" />
</template>

Obviously, you should use a similar approach to the other templates as well.

Because you use it in more than one place, you could DRY your code up and use a Vue component to apply the success/error classes:

<template>
  <span :class="cellClass"
         v-text="Number(value || 0).toFixed(toFixed || 2)" />
</template>
<script>
  export default Vue.extend({
    name: 'CellValue',
    props: ['value', 'item', 'header', 'toFixed'],
    computed: {
      cellClass() {
        return {
          'error--text': this.value < 0,
          'success--text': this.value > 0
        }
      }
    }
  })
</script>

…import it as a Vue component and use it in your table templates as:

<template v-slot:item.daily_total="cell">
  <cell-value v-bind="cell" :to-fixed="6" />
</template>

You don’t need to declare item or header as props, but they’re provided by the Vuetify slot, in case you need them.
Note I also added an extra prop called to-fixed, defaulting to 2 which determines the number of decimals. You could rename it decimals.
Also note I default the value to 0 to avoid any errors around using .toFixed() on anything that’s not of type number.
If, for example, you prefer to display a custom text when the value is of any other type than number, you could use something more elaborate in CellValue‘s template:

<template>
  <span :class="cellClass">
    <template v-if="typeof value === 'number'">
      {{ value.toFixed(toFixed || 2) }}
    </template>
    <template v-else>
      <code>{{ value || '--' }}</code>
    </template>
  </span>
</template>

For reference, I’m leaving here the initial answer, as it might help others:

Whenever your template depends on an expression which errors in some cases because it tries to access properties/methods of undefined entities, the easiest workaround is to create a computed property which avoids the exception:

<template>:

<v-row v-if="hasOpenPositions" justify="center" align="end" class="mt-1">

<script>:

computed: {
  hasOpenPositions() {
    return this.openPositions && this.openPositions.length !== 0;
  }
}

However, be warned the above computed will return true when openPositions is truthy and it doesn’t have a length property (when its length is undefined; i.e.: openPositions: {} – because undefined !== 0).

Another slightly shorter syntax I find myself using is:

computed: {
  hasOpenPositions() {
    return !!(this.openPositions?.length);
  }
}

(This one only returns true when openPositions has a truthy length, which is probably what you want).

Do note optional chaining (?.) does not work in <template>, at least for now.


The above is a general workaround which comes in handy with deep objects, so your template doesn’t error when the objects have not yet been populated/loaded.

However, if openPositions is an array, you should just instantiate it as an empty array and simplify your check as:

<template>:

<v-row v-if="openPositions.length" justify="center" align="end" class="mt-1">

<script>:

data: () => ({
  openPositions: []
}),
mounted() {
  this.$http.get('some/api').then(r => { this.openPositions = r.data })
}

The relevant bit here is openPositions is an array at all times (so it always has a length internal method) and that it’s reactive. How you update it (in mounted or some method) is irrelevant.

Leave a comment