javascriptvue.jsvuetify.jsvue-data-tables

Hiding unfilled rows in vertical v-data-table with Vue


Following is executable code to demonstrate my problem.

Template:

<div id="app">
  <v-app id="inspire">
    <v-data-table
      :headers="headers"
      :items="desserts"
      hide-default-header
      hide-default-footer
      class="elevation-1"
    ></v-data-table>
  </v-app>
</div>

Script:

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data () {
    return {
      headers: [
        {
          text: 'Dessert (100g serving)',
          align: 'start',
          value: 'name',
        },
        { text: 'Calories', value: 'calories' },
        { text: 'Fat (g)', value: 'fat' },
        { text: 'Carbs (g)', value: 'carbs' },
        { text: 'Protein (g)', value: 'protein' },
        { text: 'Iron (%)', value: 'iron' },
      ],
      desserts: [
        {
          name: 'Frozen Yogurt',
          calories: 159,
          protein: 4.0,
          iron: '1%',
        },
        {
          name: 'Ice cream sandwich',
          calories: 237,
          fat: 9.0,
          carbs: 37,
          protein: 4.3,
          iron: '1%',
        },
        {
          name: 'Eclair',
          calories: 262,
          fat: 16.0,
          carbs: 23,
          iron: '7%',
        },
        {
          name: 'Cupcake',
          calories: 305,
          fat: 3.7,
          carbs: 67,
          protein: 4.3,
          iron: '8%',
        },
        {
          name: 'Gingerbread',
          calories: 356,
          fat: 16.0,
          carbs: 49,
          protein: 3.9,
          iron: '16%',
        },
        {
          name: 'Jelly bean',
          calories: 375,
          fat: 0.0,
          carbs: 94,
          protein: 0.0,
          iron: '0%',
        },
        {
          name: 'Lollipop',
          calories: 392,
          fat: 0.2,
          carbs: 98,
          protein: 0,
          iron: '2%',
        },
        {
          name: 'Honeycomb',
          calories: 408,
          fat: 3.2,
          iron: '45%',
        },
        {
          name: 'Donut',
          calories: 452,
          fat: 25.0,
          carbs: 51,
          protein: 4.9,
          iron: '22%',
        },
        {
          name: 'KitKat',
          carbs: 65,
          protein: 7,
          iron: '6%',
        },
      ],
    }
  },
})

This is the result: wide-screen

Looks all right with larger screens. But when I do have smaller screens, it starts to look like this:

small-screen

Question: how do I hide the empty parts of the table at smaller screens(/when everything just becomes one column).


Solution

  • You can assign prop value in v-data-table mobile-breakpoint="0", so now you can add your custom functionality on your desired screen size. On windows resize I'm calling the function onResize to calculate the width of the current window, and assign value to the isMobile variable to true if the window width is less than 769 (you can change this value), now we will add <template v-slot:item="{ item }"> in the v-data-table to use our custom design as shown on demo. Different designs on the base of isMobile value.

    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
     data: () => ({
       isMobile: false,
           windowSize: {
            x: 0,
            y: 0,
          },
           headers: [
            {
              text: 'Dessert (100g serving)',
              align: 'start',
              sortable: false,
              value: 'name',
            },
            { text: 'Calories', value: 'calories' },
            { text: 'Fat (g)', value: 'fat' },
            { text: 'Carbs (g)', value: 'carbs' },
            { text: 'Protein (g)', value: 'protein' },
            { text: 'Iron (%)', value: 'iron' },
          ],
           desserts: [
            {
              name: 'Frozen Yogurt',
              calories: 159,
              protein: 4.0,
              iron: '1%',
            },
            {
              name: 'Ice cream sandwich',
              calories: 237,
              fat: 9.0,
              carbs: 37,
              protein: 4.3,
              iron: '1%',
            },
            {
              name: 'Eclair',
              calories: 262,
              fat: 16.0,
              carbs: 23,
              iron: '7%',
            },
            {
              name: 'Cupcake',
              calories: 305,
              fat: 3.7,
              carbs: 67,
              protein: 4.3,
              iron: '8%',
            },
            {
              name: 'Gingerbread',
              calories: 356,
              fat: 16.0,
              carbs: 49,
              protein: 3.9,
              iron: '16%',
            },
            {
              name: 'Jelly bean',
              calories: 375,
              fat: 0.0,
              carbs: 94,
              protein: 0.0,
              iron: '0%',
            },
            {
              name: 'Lollipop',
              calories: 392,
              fat: 0.2,
              carbs: 98,
              protein: 0,
              iron: '2%',
            },
            {
              name: 'Honeycomb',
              calories: 408,
              fat: 3.2,
              iron: '45%',
            },
            {
              name: 'Donut',
              calories: 452,
              fat: 25.0,
              carbs: 51,
              protein: 4.9,
              iron: '22%',
            },
            {
              name: 'KitKat',
              carbs: 65,
              protein: 7,
              iron: '6%',
            },
          ],
      
      }),
      mounted() {
        this.onResize();
      },
    
      methods: {
           onResize() {
          this.windowSize = { x: window.innerWidth, y: window.innerHeight };
    
            if (this.windowSize.x < 769) {
             this.isMobile = true; 
            } else{
               this.isMobile = false;
              }
          }
      },
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.24.0/axios.min.js"></script>
    <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/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>
    
    
     <div id="app">
      <v-app id="inspire">
       <div v-resize="onResize" class="pt-20">
        <v-data-table
          :headers="headers"
          :items="desserts"
          :items-per-page="5"
          class="elevation-1"
          hide-default-header
          hide-default-footer
          mobile-breakpoint="0"          
        >
           <template v-slot:item="{ item }">
                    <tr v-if="isMobile == false">
                      <td>{{ item.name }} not mobile view</td>
                      <td class="text-xs-right">{{ item.calories }}</td>
                      <td class="text-xs-right">{{item.fat }}</td>
                      <td class="text-xs-right">{{ item.carbs }}</td>
                      <td class="text-xs-right">{{ item.protein }}</td>
                      <td class="text-xs-right">{{ item.iron }}</td>
                    </tr>
                    <tr v-else>
                      <td>
                        <v-list-item-group>
              <v-list-item v-if="item.name  != undefined">
                <v-list-item-content>
                  <v-list-item-title v-text="item.name "></v-list-item-title>
                </v-list-item-content>
              </v-list-item>
              
               <v-list-item v-if="item.calories  != undefined">
                <v-list-item-content>
                  <v-list-item-title v-text="item.calories "></v-list-item-title>
                </v-list-item-content>
              </v-list-item>
              
                <v-list-item v-if="item.fat  != undefined">
                <v-list-item-content>
                  <v-list-item-title v-text="item.fat "></v-list-item-title>
                </v-list-item-content>
              </v-list-item>
              
               <v-list-item v-if="item.carbs  != undefined">
                <v-list-item-content>
                  <v-list-item-title v-text="item.carbs "></v-list-item-title>
                </v-list-item-content>
              </v-list-item>
              
                <v-list-item v-if="item.protein  != undefined">
                <v-list-item-content>
                  <v-list-item-title v-text="item.protein "></v-list-item-title>
                </v-list-item-content>
              </v-list-item>
              
               <v-list-item v-if="item.iron  != undefined">
                <v-list-item-content>
                  <v-list-item-title v-text="item.iron "></v-list-item-title>
                </v-list-item-content>
              </v-list-item>
              
              
            </v-list-item-group>
                      </td>
                    </tr>
                  </template>
        </v-data-table>
                 </div>
        </v-app>
    </div>