Vuetify - change style of select input in table footer

Viewed 1424

We are using Vuetify for our application where the whole application is using outlined text/select fields like this:

Example of outlined text fields as per our application's style

This is our table definition from the docs:

<v-data-table
    :headers="headers"
    :items="desserts"
    :items-per-page="5"
    class="elevation-1"
  ></v-data-table>

But that makes the table like this:

Table with "Rows per page" select field that doesn't follow the outlined input style

As you can see, tables by default use the common Material text field style. Can you tell me how to change this select field to our outlined style? Thank you.

2 Answers

You could change select field to outlined style by using available slots of the v-data-table component. In your case use a footer slot. Slot receives the following parameters:

{
  props: {
    options: {
      page: number
      itemsPerPage: number
      sortBy: string[]
      sortDesc: boolean[]
      groupBy: string[]
      groupDesc: boolean[]
      multiSort: boolean
      mustSort: boolean
    },
    pagination: {
      page: number
      itemsPerPage: number
      pageStart: number
      pageStop: number
      pageCount: number
      itemsLength: number
    },
    itemsPerPageText: string
  },
  on: {}
  headers: TableHeader[]
  widths: []
}

You could create a custom component that will use the parameters as props and render the select component with the outlined property.

<template>
  <v-select :items="items" label="Outlined style" outlined></v-select>
</template>

<script>
export default {
  name: "vue-custom-component",
  data: function () {
    return {
      items: [],
    };
  },
  props: {
    currentPage: {
      type: Number,
      required: true,
    },
    itemsPerPage: {
      type: Number,
      required: true,
    },
    itemsLength: {
      type: Number,
      required: true,
    },
    pageCount: {
      type: Number,
      required: true,
    },
  },
  mounted() {
    //here you could fill items
  },
};
</script>

<style lang='scss'>
</style>

Example of using the custom component in footer slot.

<v-data-table
  :items="items"
>
  <template v-slot:footer="{ props }">
    <v-row align="center">
      <v-col class="d-flex" cols="12" sm="6">
        <vue-custom-component
          :currentPage="props.pagination.page"
          :itemsPerPage="props.pagination.itemsPerPage"
          :itemsLength="props.pagination.itemsLength"
          :pageCount="props.pagination.pageCount"
        ></vue-custom-component>
      </v-col>
    </v-row>
  </template>
</v-data-table>

Here you could find details

I think it's not possible to change the style of the input directly.

Instead you can hide the default footer and add your customer footer.

Here is an example:

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data () {
    return {
      page: 1,
      pageCount: 0,
      itemsPerPage: 10,
      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,
          fat: 6.0,
          carbs: 24,
          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,
          protein: 6.0,
          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,
          carbs: 87,
          protein: 6.5,
          iron: '45%',
        },
        {
          name: 'Donut',
          calories: 452,
          fat: 25.0,
          carbs: 51,
          protein: 4.9,
          iron: '22%',
        },
        {
          name: 'KitKat',
          calories: 518,
          fat: 26.0,
          carbs: 65,
          protein: 7,
          iron: '6%',
        },
      ],
    }
  },
})
<head>
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/vuetify@2.3.7/dist/vuetify.min.css">
  <script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/vuetify@2.3.7/dist/vuetify.min.js"></script>
</head>

<body>
  <div id="app">
    <v-app id="inspire">
      <div>
        <v-data-table
          :headers="headers"
          :items="desserts"
          :page.sync="page"
          :items-per-page="itemsPerPage"
          hide-default-footer
          class="elevation-1"
          @page-count="pageCount = $event"
        ></v-data-table>
        <div class="text-center pt-2">
          <v-pagination v-model="page" :length="pageCount"></v-pagination>
          <v-text-field
            :value="itemsPerPage"
            label="Items per page"
            type="number"
            outlined
            min="-1"
            max="15"
            @input="itemsPerPage = parseInt($event, 10)"
          ></v-text-field>
        </div>
      </div>
    </v-app>
  </div>
</body>

Reference

https://vuetifyjs.com/en/components/data-tables/#external-pagination

Related