'Condition on template with v-if using v-slot prop

I'm trying to make a condition to enable a named slot like this:

<template v-slot:item="{ item }" v-if="item.loading">
  <v-progress-circular indeterminate color="primary"></v-progress-circular>
</template>

My use case is a Vuetify datatable: each item has a "loading" property, and I'd like to activate "item" slot only if the row is loading ("item" slot is Slot to replace the default rendering of a row)

The error is that item is undefined in the v-if, which seems logic : item is only defined for template children tag.

Is there a way to solve this problem?



Solution 1:[1]

You can filter the items that you pass to the datatable with a computed property.

Can you just not swap element based on loading ?

Vue.config.devtools = false;
Vue.config.productionTip = false;

var app = new Vue({
  el: '#app',
  data: {
    items: [{data : "", loading: true}, {data : "Some data", loading: false}]
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <div v-for="item in items">
    <div>
      <div v-if="item.loading">
        Loading...
      </div>
      <div v-else>
        {{item.data}}
      </div>
    </div>

  </div>
</div>

Solution 2:[2]

I had a similar problem, and I solved it in Vuetify 2 by importing VDataTable/Row as 'v-data-table-row', and using it to render 'regular' table rows, and for custom rows I used my own template.

JavaScript

    import Row from 'vuetify/lib/components/VDataTable/Row.js';

    export default {
        components: { 'v-data-table-row': Row },
        data() {
            return {
                currentItemName: 'Ice cream sandwich'
            }
        }
         // headers, items, etc...
    }

HTML

    <template v-slot:item="{ item }">
      <tr v-if="item.name == currentItemName" class="blue-grey lighten-4">
        <td>Custom prefix - {{ item.name }}</td>
        <td colspan="2">{{ item.calories }} - Custom suffix</td>
      </tr>
      <v-data-table-row v-else :headers="headers" :item="item">
        <template
          v-for="(index, name) in $scopedSlots"
          v-slot:[name.substr(5)]="data"
        >
          <slot
            v-if="name.substr(0, 5) === 'item.'"
            :name="name"
            v-bind="data"
          ></slot>
        </template>
      </v-data-table-row> </template

You can check out working example here.

Solution 3:[3]

You can just put the v-if on the child element

<template #item="{ item }">
    <v-progress-circular
        v-if="item.loading"
        color="primary"
        indeterminate
    ></v-progress-circular>
</template>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 domaci_a_nas
Solution 3