tutorial

How to Use the Vuetify Carousel Component

A carousel is useful for displaying many images in a cyclic view. It comes with functionality that allows users to view the images one after the other. It allows multiple pieces of related visual content to occupy the same screen space. In this article, we’re to learn how to create and customize carousels using Vuetify.

The v-carousel component

Vuetify provides the v-carousel component for creating carousels. We can create a slide in the carousel by adding a new v-carousel-item component to the v-carousel. Here we’re creating 7 slides, each for a color of the rainbow.

<template>
  <v-app>
    <v-carousel>
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

The carousel will always show the first slide by default:

Creating a carousel.

We can change the current slide with the displayed arrows. The left arrow will show the previous slide, while the right arrow will show the next slide:

Clicking the right arrow on the carousel to display the next slide.

The carousel comes with delimiters that indicate the number of slides the carousel has and the one it is currently showing. v-carousel comes with the delimiter-icon prop which allows us to customize the delimiter icons with any of the available icons.

<template>
  <v-app>
    <v-carousel delimiter-icon="mdi-minus">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Using custom carousel delimiter icons.

Use the transition prop to customize the transition the carousel uses to display the next image.

<template>
  <v-app>
    <v-carousel>
      <v-carousel-item
        v-for="color in colors"
        :key="color"
        transition="fade-transition"
      >
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

You can also change the transition the carousel uses to display the previous image, with the reverse-transition prop:

<template>
  <v-app>
    <v-carousel>
      <v-carousel-item
        v-for="color in colors"
        :key="color"
        transition="fade-transition"
        reverse-transition="fade-transition"
      >
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

Cycle

Setting the cycle prop to true on a v-carousel will make it automatically transition to the next slide after a set amount of time.

<template>
  <v-app>
    <v-carousel cycle>
      <v-carousel-item
        v-for="color in colors"
        :key="color"
      >
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

Interval

By default, the carousel shows each slide for an interval of 6 seconds before automatically transitioning to the next slide when the cycle prop is set to true. We can modify this interval with the interval prop.

<template>
  <v-app>
    <v-carousel cycle interval="1000">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

Hiding navigation controls

We can hide the navigation controls of the carousel by setting the show-arrows prop to false:

<template>
  <v-app>
    <v-carousel :show-arrows="false">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Hiding carousel navigation controls.

We might want to have the carousel only display its navigation controls when the mouse hovers over it. We can do this by setting the show-arrows-on-hover prop to true:

<template>
  <v-app>
    <v-carousel :show-arrows-on-hover="true">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

Now it’s only when you hover over the carousel with the mouse that you see its controls:

Making the carousel only display its arrows on hover.

Customized arrows

We can customize the carousel arrows with the prev and next slots.

<template>
  <v-app>
    <v-carousel>
      <template v-slot:prev="{ on, attrs }">
        <v-btn color="green" v-bind="attrs" v-on="on"> Previous </v-btn>
      </template>
      <template v-slot:next="{ on, attrs }">
        <v-btn color="blue" v-bind="attrs" v-on="on">Next</v-btn>
      </template>
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({

    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Customize the carousel arrows.

Setting the hide-delimiters prop to true will hide the bottom controls of the carousel.

<template>
  <v-app>
    <v-carousel hide-delimiters>
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Hiding the carousel delimiters.

Two-way binding with v-model

We can use v-model on the v-carousel to set up a two-way binding between the current carousel slide and a variable. In the code below, we create a carousel and some text below it that displays the index of the current slide with the carousel variable:

<template>
  <v-app
    <v-carousel v-model="carousel">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
    <div class="d-flex justify-center mt-2">Slide: {{ carousel }}</div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    carousel: 0,
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Displaying the index of the currently displayed slide of the carousel.

Changing the displayed carousel slide updates carousel, which updates the text:

Change the currently displayed carousel slide updates the text.

Now let’s add two buttons below the text to change the displayed carousel slide:

<template>
  <v-app>
    <v-carousel v-model="carousel">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
    <div class="d-flex justify-center mt-2">Slide: {{ carousel }}</div>
    <div class="d-flex justify-center mt-2">
      <v-btn class="mr-2" color="green" dark @click="carousel--"
        >Previous</v-btn
      >
      <v-btn class="ml-2" color="blue" dark @click="carousel++">Next</v-btn>
    </div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    carousel: 0,
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Adding two buttons to change the carousel slide.

The “Previous” button decrements carousel which takes the carousel to the previous slide, while the “Next” button increments carousel to transition the carousel to the next slide:

Clicking the "Next" button transitions the carousel to the next slide.

Conclusion

We use a carousel in a user interface to display a number of related visual content in the same screen space. Use the v-carousel and v-carousel-item components to create a carousel and customize its behavior and appearance.

How to Use the Vuetify Date Picker Component

We use a date picker to let users select a date or a range of dates. In this article, we’re going to learn about the Vuetify date picker component and how it lets us create and customize date pickers.

The v-date-picker Component

Vuetify provides the v-date-picker component for creating date pickers.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>

The current date is shown by default:

A date picker.

We can select this current date if we want:

Selecting the current date in a date picker.

Or another date:

Select another date in the date picker.

Two-way Binding with v-model

We can use v-model on the date picker component to set up a two-way binding between the picker and a variable. In the code below, we create a date picker and add some text below it to display the value of the date variable, which is the date selected on the picker.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker v-model="date"></v-date-picker>
    </div>
    <div class="d-flex justify-center mt-2">Date: {{ date || 'No date' }}</div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
};
</script>

Initially, date is null, meaning that no date has been selected. We display a text “No date” to indicate this:

Initially, no date is selected on the date picker.

Once we select a date, date is updated by the binding and the text shows it. The date is set to a string in the YYYY-MM-DD format:

The text shows the selected date in the YYYY-MM-DD format

Allowed Dates

We can specify allowed dates on the date picker with the allowed-dates prop. Here, we’re passing a function to it that takes the string value of the date and returns a boolean value that indicates whether the date should be allowed or not.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker
        v-model="date"
        :allowed-dates="allowedDates"
      ></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
  methods: {
    allowedDates: (val) => parseInt(val.split('-')[2], 10) % 2 === 1,
  },
};
</script>

The function we wrote will only allow a date with an odd day to be selectable on the picker:

Only dates with an odd day are selectable on the date picker.

Date Picker Colors

We can customize the color of the date picker with the color and header-color props.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker v-model="date" color="green"></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
};
</script>

We don’t specify a header-color in the code above, so the header color will be set to the value of the color prop:

Customizing the date picker color.

Here we do set a header-color, and the color of the date picker reflects this:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker
        v-model="date"
        color="green"
        header-color="primary"
      ></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
};
</script>

Customizing the date picker header color.

Date Picker Elevation

We can set the elevation of a date picker with the elevation prop. The v-date-picker component supports elevation up to a maximum of 24.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker v-model="date" elevation="20"></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
};
</script>
Customizing the date picker elevation.

Date Picker Icons

We can override the default icons the date picker uses with the year-icon, prev-icon and next-icon props.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker
        v-model="date"
        year-icon="mdi-calendar-blank"
        prev-icon="mdi-skip-previous"
        next-icon="mdi-skip-next"
      ></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
};
</script>
Customizing date picker icons.

Multiple Selection

We use the multiple prop to allow users to select multiple dates from the picker. When the multiple prop is set to true, the date picker component will expect the variable passed to its v-model to be an array.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker v-model="dates" multiple></v-date-picker>
    </div>
    <div class="d-flex justify-center">Selected: {{ dates }}</div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    dates: [],
  }),
};
</script>
A date picker with no dates selected.
A date picker with no dates selected.
A date picker with 4 dates selected.
A date picker with 4 dates selected.

picker-date Sync

We can use the .sync modifier to watch the picker-date, which is the displayed month/year (depending on the picker type and active view). In the code below, we create a date picker and text below it that displays pickerDate, a variable synced to the picker-date prop using picker-date.sync.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker
        v-model="date"
        :picker-date.sync="pickerDate"
      ></v-date-picker>
    </div>
    <div class="d-flex justify-center">Month: {{ pickerDate }}</div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
    pickerDate: null,
  }),
};
</script>
Using the picker-date prop

When we change the month on the date picker (using the arrows), pickerDate is updated:

The pickerDate variable is updated when we change the month.

Date Picker Range

Use the range prop on a date picker component to allow users select a range of dates from it. When using the range prop, v-date-picker expects the value passed to its v-model to be an array of length 2 or empty.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker v-model="dates" range></v-date-picker>
    </div>
    <div class="d-flex justify-center">Model: {{ dates }}</div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    dates: ['2022-03-05', '2022-03-15'],
  }),
};
</script>
Selecting a range of dates on the date picker.

We can select another date range if we want:

Selecting another date range on the date picker.

Readonly Date Picker

We can use the readonly prop to turn off interactivity with a date picker:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker v-model="date" readonly></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
};
</script>

Here’s how it looks when its readonly and you try to pick another date, say March 16:

Attempting to pick a date on a readonly date picker.

Show Current

By default, the date picker indicates the current date with the outline of a circle:

The date picker indicates the current date with the outline of a circle.

We can remove this outline by setting the show-current prop to false:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker v-model="date" :show-current="false"></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
};
</script>

We can also make the date picker indicate another date as the current date. We do this by setting the show-current prop to a date string in the YYYY-MM-DD format:

Indicating another date as the current date on a date picker.

Showing Sibling Months

By default, days from the previous and next months are not visible. Use the show-adjacent-months prop to display them:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker v-model="date" show-adjacent-months></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
};
</script>
Showing sibling months on the date picker.
Days from February and April are displayed on the date picker.

Customizing the Date Picker Width

We can customize the width of the date picker using the width prop:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker v-model="date" width="400"></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
  }),
};
</script>
Setting a custom date picker width.

Full Width

We can also use the full-width prop to make the date picker take up all the available width of its parent:

Date Picker Event Dates

We can specify events by assigning arrays, objects or functions to the events prop. And we can the event-color prop to change the default color of the mark the date picker uses to indicate the events. Here, we set events to all the odd number days in the month of March 2022 to mark them.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-date-picker
        v-model="date"
        :events="eventDates"
        event-color="green"
      ></v-date-picker>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    date: null,
    eventDates: null,
  }),
  mounted() {
    this.eventDates = [...Array(31)]
      .map((value, index) => index + 1)
      .filter((value) => value % 2 === 0)
      .map((value) => {
        const date = new Date();
        date.setDate(value);
        return date.toISOString().substr(0, 10);
      });
  },
};
</script>
Setting event dates on the date picker.

Summary

We use date pickers to allow users select a date or a range of dates. Vuetify provides the v-date-picker component for creating and customizing date pickers.

How to Use the Vuetify Switch Component

A switch allows a user to choose between two distinct values.

You can use them in place of a checkbox in your UI.

In this article, we’re going to learn about the Vuetify switch component and the different ways of customizing it.

The v-switch component

v-switch is the name of the component Vuetify provides for creating a switch:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-switch></v-switch>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A switch turned off.

Clicking the switch turns it on:

A switch turned on.

Two-way binding with v-model

We can set up a two-way binding between the value of the switch and a variable with v-model. In the code below, we’ve created a switch and a button below it for turning it off. We added a click handler to the button that will set switch1 to false, which will turn the switch off due to the v-model. The two-way binding also ensures that toggling the switch in the user interface will update switch1.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-switch v-model="switch1"></v-switch>
    </div>
    <div class="d-flex justify-center mt-2">
      <v-btn color="primary" @click="switch1 = false">Turn off</v-btn>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    switch1: false,
  }),
};
</script>
A switch and a button to turn it off.

Clicking the button turns off the switch:

Clicking the button turns off the switch:

Switch labels

We can explain the function of a switch to users with the label prop:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-switch
        v-model="switch1"
        :label="`Switch: ${switch1 ? 'on' : 'off'}`"
      ></v-switch>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    switch1: false,
  }),
};
</script>
A turned off switch with a label.

Custom HTML labels

To include HTML in the label of a switch, use the label slot:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-switch v-model="switch1">
        <template v-slot:label>
          Switch:
          <b :class="{ 'primary--text': switch1 }">{{
            switch1 ? 'on' : 'off'
          }}</b>
        </template>
      </v-switch>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    switch1: false,
  }),
};
</script>

Custom colors

Like many other Vuetify components, v-switch comes with the color prop which allows us to set a custom color:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="4" class="d-flex justify-center"
        ><v-switch color="red" label="red"></v-switch>
      </v-col>
      <v-col sm="4" class="d-flex justify-center"
        ><v-switch color="primary" label="primary"></v-switch>
      </v-col>
      <v-col sm="4" class="d-flex justify-center"
        ><v-switch color="green" label="green"></v-switch>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Switch components with custom colors.

Flat switch

We can use the flat prop to remove the elevation on the thumb of a switch.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-switch
        v-model="switch1"
        :label="`Switch: ${switch1 ? 'on' : 'off'}`"
        flat
      ></v-switch>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    switch1: false,
  }),
};
</script>
A flat switch turned off.
A flat switch turned on.

Switch in inset mode

To render a switch in inset mode, set the inset prop to true:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-switch
        v-model="switch1"
        :label="`Switch: ${switch1 ? 'on' : 'off'}`"
        inset
      ></v-switch>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    switch1: false,
  }),
};
</script>
A turned off switch in inset mode.
A turned on switch in inset mode.

Pass array to v-model

We can pass a shared array variable to the v-models of multiple switch components.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      {{ people }}
    </div>

    <div class="d-flex justify-center mt-2">
      <v-switch
        v-model="people"
        color="primary"
        label="Peter"
        value="Peter"
      ></v-switch>
    </div>
    <div class="d-flex justify-center mt-2">
      <v-switch
        v-model="people"
        color="primary"
        label="Daniel"
        value="Daniel"
      ></v-switch>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    people: [],
  }),
};
</script>
Switch components sharing a single array variable.

Toggling any one of the switches will update the array:

Toggling one of the switch components will update the array.

Disabled switch

We can use the disabled prop to disable a switch:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-switch label="off disabled" :value="false" disabled></v-switch>
    </div>
    <div class="d-flex justify-center mt-2">
      <v-switch label="on disabled" :value="true" disabled></v-switch>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Disabled switch components.

Switch in loading state

Use the loading prop to set a switch to the loading state:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-switch label="off loading" :value="false" loading="primary"></v-switch>
    </div>
    <div class="d-flex justify-center mt-2">
      <v-switch label="on loading" :value="true" loading="primary"></v-switch>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Switch components in the loading state.

Key takeaways

Switches are useful for taking boolean input from users.

Use the v-switch component and its various props to create and customize them.

How to Use the Vuetify Radio Button Component

A radio button is useful when you need to obtain user input from a group of options. For example, a user can select a preferred language or country with it. In this article, we’re going to learn how to create and customize a radio button using Vuetify.

The Vuetify Radio Button Component

Use the v-radio component to create a basic radio button:

<template>
  <v-app>
    <div class="d-flex justify-center mt-4">
      <v-radio></v-radio>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A basic radio button.

Radio Button Labels

To describe a radio button to the user, we can use the label prop:

<template>
  <v-app>
    <div class="d-flex justify-center mt-4">
      <v-radio label="Radio"></v-radio>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A radio button with a label.

Radio buttons are typically used with radio groups in Vuetify. We can do this by wrapping all the v-radios in a v-radio-group. We can then set up a two-way binding with the radio group component through v-model, which will allow us to access and set the currently selected radio button in the group:

<template>
  <v-app>
    <div class="d-flex justify-center mt-4">
      <v-radio-group v-model="radioGroup">
        <v-radio
          v-for="n in 3"
          :key="n"
          :label="`Radio ${n}`"
          :value="n"
        ></v-radio>
      </v-radio-group>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    radioGroup: 1,
  }),
};
</script>
A group of radio buttons.

Clicking on another radio button in the group will update the variable and change the selection:

Selecting a radio button in the group changes the selection.

Radio Button Custom Colors

The radio button component has a color prop that we can use to customize its color:

<template>
  <v-app>
    <div class="d-flex justify-center mt-4">
      <v-radio-group v-model="radioGroup">
        <v-radio
          v-for="(color, i) in colors"
          :key="i"
          :label="color"
          :value="color"
          :color="color"
        ></v-radio>
      </v-radio-group>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['indigo', 'yellow', 'error', 'green', 'primary'],
  }),
};
</script>
The radio button with the yellow color is selected.
The radio button with the Vuetify theme primary color is selected.

Radio Button Directions

We can use the row prop to present the radio buttons horizontally:

<template>
  <v-app>
    <div class="d-flex justify-center mt-4">
      <v-radio-group v-model="radioGroup" row>
        <v-radio
          v-for="i in 3"
          :key="i"
          :label="`Option ${i}`"
          :value="i"
        ></v-radio>
      </v-radio-group>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A group of horizontally presented radio buttons.

The column prop will present radio buttons vertically, and is the default direction:

<template>
  <v-app>
    <div class="d-flex justify-center mt-4">
      <v-radio-group v-model="radioGroup" column>
        <v-radio
          v-for="i in 3"
          :key="i"
          :label="`Option ${i}`"
          :value="i"
        ></v-radio>
      </v-radio-group>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A group of vertically presented radio buttons.

Ensuring a Mandatory Value

To make sure a radio group always has a value, set the mandatory prop to true:

<template>
  <v-app>
    <div class="d-flex justify-center mt-4">
      <v-radio-group v-model="radioGroup" mandatory>
        <v-radio
          v-for="i in 3"
          :key="i"
          :label="`Option ${i}`"
          :value="i"
        ></v-radio>
      </v-radio-group>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
The radio group has a mandatory value.

Labels with HTML

If we want to include HTML in the label of a radio group, we can put the content in the label slot of the v-radio-group:

<template>
  <v-app>
    <div class="d-flex justify-center mt-4">
      <v-radio-group v-model="radioGroup" mandatory>
        <template v-slot:label> Pick an <strong>option</strong> </template>
        <v-radio
          v-for="i in 3"
          :key="i"
          :label="`Option ${i}`"
          :value="i"
        ></v-radio>
      </v-radio-group>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A radio group with a label containing HTML content.

We can also include HTML in the labels of the radio buttons with their own label slots:

<template>
  <v-app>
    <div class="d-flex justify-center mt-4">
      <v-radio-group v-model="selected">
        <template v-slot:label>
          Select your default <strong>search engine</strong>
        </template>
        <v-radio v-for="(url, name) in searchEngines" :key="name" :value="name"
          ><template v-slot:label
            ><a :href="url">{{ name }}</a></template
          ></v-radio
        >
      </v-radio-group>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selected: 'Google',
    searchEngines: {
      Bing: 'https://bing.com',
      Google: 'https://google.com',
      Duckduckgo: 'https://duckduckgo.com',
    },
  }),
};
</script>
A group of radio buttons with labels containing HTML content.

Summary

We can create a group of radio buttons when we want to receive user input from a predefined set of options. Vuetify provides the v-radio component to create radio buttons and the v-radio-group component to add groupable functionality to them. These components come with various props for customization.

How to Use the Vuetify Slider Component

Sliders are a great way of getting user input from a range of values. There are used for various functions like adjusting the brightness of a display or tuning speaker volumes. In this post, we’re going to explore the various ways we can create and customize sliders with Vuetify.

The v-slider Component

Vuetify provides the v-slider component for creating sliders:

<template>
  <v-app>
    <v-row justify="center" class="mt-2">
      <v-col sm="6">
        <v-slider></v-slider>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Creating a slider with the v-slider component.

A basic slider consists of a track (the long line) and a thumb (the circle). Clicking somewhere on the track moves the thumb to that location:

Clicking on a point on the track moves the thumb there.

Slider Labels

To describe our sliders to users, we can specify a label with the label prop:

<template>
  <v-app>
    <v-row justify="center" class="mt-2">
      <v-col sm="6">
        <v-slider label="Slider"></v-slider>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A Vuetify slider with a label.

Slider Hints

We can show hints for a slider with the hint prop.

<template>
  <v-app>
    <v-row justify="center" class="mt-2">
      <v-col sm="6">
        <v-slider label="Slider" hint="hint"></v-slider>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>

The hint shows up when you click the thumb:

Two-way Binding with v-model

We can use v-model to create a two-way binding between the slider value and a variable.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider label="Slider" hint="hint" v-model="sliderValue"></v-slider>
      </v-col>
    </div>
    <div class="d-flex justify-center">
      <v-col sm="6">Slider value: {{ sliderValue }}</v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sliderValue: 0,
  }),
};
</script>

In the code above, we’re adding in some text to display the current value of the slider (determined by sliderValue):

A slider with text below it to display its numeric value.

When the slider receives input sliderValue is updated and the text reflects this:

The text is updated with the new slider value when it changes.

Let’s add a “Reset” button:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider label="Slider" hint="hint" v-model="sliderValue"></v-slider>
      </v-col>
    </div>
    <div class="d-flex justify-center">
      <v-col sm="6">Slider value: {{ sliderValue }}</v-col>
    </div>
    <div class="d-flex justify-center">
      <v-col sm="6"
        ><v-btn color="primary" @click="sliderValue = 0"
          >Reset slider</v-btn
        ></v-col
      >
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sliderValue: 0,
  }),
};
</script>
Adding a "Reset" button.

We added a click handler to the button that sets sliderValue to 0 when it is clicked:

Clicking the "Reset" button sets the slider value back to 0 when it is clicked.

Slider Min and Max Values

Vuetify sliders have default min and max values of 0 and 100 respectively. We can change them to something else with the min and max props:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider
          label="Slider"
          hint="hint"
          v-model="sliderValue"
          min="20"
          max="60"
        ></v-slider>
      </v-col>
    </div>
    <div class="d-flex justify-center">
      <v-col sm="6">Slider value: {{ sliderValue }}</v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sliderValue: null,
  }),
};
</script>

Now the minimum value of the slider is 20:

The minimum value of the slider is now 20.

And the maximum value is now 60:

The maximum value of the slider is now 60.

Slider Custom Colors

v-slider comes with props that allow us to modify the colors of its various elements.

Use the color prop to change the color of the part of the track before the thumb:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider label="color" v-model="sliderValue" color="green"></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sliderValue: 0,
  }),
};
</script>
Changing the color of the part of the track before the slider thumb.

The track-color prop will modify the color of the part of the track after the thumb:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider
          label="track-color"
          v-model="sliderValue"
          track-color="red"
        ></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sliderValue: 0,
  }),
};
</script>
Modifying the color of the part of the track after the slider thumb.

To change the color of the thumb, use the thumb-color prop:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider
          label="thumb-color"
          v-model="sliderValue"
          thumb-color="orange"
          thumb-label="always"
        ></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sliderValue: 0,
  }),
};
</script>
Changing the color of the slider thumb.

Disabled Sliders

Set the disabled prop to true to turn off interactivity with the slider:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider disabled value="50" label="Disabled"></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A disabled slider.

Discrete Sliders

By default Vuetify sliders have a step value of 1. These type of sliders are called continuous sliders because the thumb moves smoothly from its min to max value. In cases where we need less precision we can increase this step value, with the step prop:

<template>
  <v-app>
    <div class="d-flex justify-center mt-10">
      <v-col sm="6">
        <v-slider
          v-model="sliderValue"
          step="10"
          thumb-label="always"
        ></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sliderValue: 0,
  }),
};
</script>
A discrete slider.

Slider Icons

v-slider provides props to display icons along with the slider, useful for adding more context.

The prepend-icon prop will display the accompanying icon before the slider:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider v-model="volume" prepend-icon="mdi-volume-high"></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    volume: 0,
  }),
};
</script>
Displaying an icon before a slider with the prepend-icon prop.

The append-icon will show the icon after the slider:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider v-model="volume" append-icon="mdi-volume-high"></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    volume: 0,
  }),
};
</script>
Displaying an icon after a slider with the append-icon prop.

Readonly Sliders

Readonly sliders also prevent interactivity like disable sliders, but they don’t lose their color:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider readonly value="30" label="Readonly"></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A readonly slider.

Inverse Labels

To display the slider label at the end of the slider, use the inverse-label prop:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider label="Inverse label" inverse-label></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Display the label at the end of the slider with the inverse-label prop.

Slider Thumbs

v-slider offers certain props for customizing the behaviour and display of the thumb. Set the thumb-label prop to true to display to only display the thumb label when the slider is being used:

<template>
  <v-app>
    <div class="d-flex justify-center mt-10">
      <v-col sm="6">
        <v-slider v-model="value" label="Slider" thumb-label></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 0,
  }),
};
</script>
The thumb displays only when the slider is being used.

To always show the thumb label whether the user is using the slider or not, set the thumb-label prop to always:

<template>
  <v-app>
    <div class="d-flex justify-center mt-10">
      <v-col sm="6">
        <v-slider v-model="value" label="Slider" thumb-label="always"></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 0,
  }),
};
</script>
Making the slider thumb display all the time.

Custom Thumb Sizes

The thumb-size prop lets us modify the thumb size:

<template>
  <v-app>
    <div class="d-flex justify-center mt-16">
      <v-col sm="6">
        <v-slider
          v-model="value"
          label="Slider"
          thumb-label="always"
          thumb-size="50"
        ></v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 0,
  }),
};
</script>
Modifying the slider thumb size.

Custom Thumb Labels

The thumb normally displays the current numeric value of the slider, but we change what it shows by providing an element to the thumb-label slot of v-slider:

<template>
  <v-app>
    <div class="d-flex justify-center mt-16">
      <v-col sm="6">
        <v-slider
          v-model="value"
          label="Volume"
          thumb-label="always"
          thumb-size="50"
        >
          <template v-slot:thumb-label>
            <v-icon dark>mdi-volume-high</v-icon>
          </template>
        </v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 0,
  }),
};
</script>
A slider with a custom thumb label.

Slider Ticks

Ticks visually represent the values the user can move the slider to. Setting the ticks prop to true will show the slider only when the slider is being used:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider v-model="value" step="10" ticks> </v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 0,
  }),
};
</script>
The ticks display only when the slider is being used.

Set ticks to always to make the ticks display all the time:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider v-model="value" step="10" ticks="always"> </v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 0,
  }),
};
</script>
A slider with ticks that display all the time.

Custom Tick Sizes

We can also customize the tick size, with the tick-size prop:

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="6">
        <v-slider v-model="value" step="10" ticks="always" tick-size="4">
        </v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 0,
  }),
};
</script>
A slider with a custom tick size.

Tick Labels

We can add text to describe the ticks. To do this, set the tick-labels prop to an array of strings.

<template>
  <v-app>
    <div class="d-flex justify-center mt-2">
      <v-col sm="12">
        <v-slider
          v-model="value"
          step="10"
          ticks="always"
          :tick-labels="tickLabels"
        >
        </v-slider>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 0,
    tickLabels: ['Terrible!', 'Bad', 'Okay', 'Good', 'Excellent!'],
  }),
};
</script>

Each item of the array will be assigned to a tick:

A slider with tick labels.

Summary

Vuetify provides the v-slider component to create sliders. We can use its props to customize various aspects of its behaviour and appearance.

Vuetify Margin and Padding: A Complete Guide

Space is a fundamental element of visual design and is important in every user interface. When building web apps, we usually space out elements from one another by modifying their paddings and margins. Vuetify provides spacing helper classes for adjusting the padding and margin of elements without having to create new classes. We’re going to learn how to use them in this post.

All the Vuetify helper classes are of the following format: {property}{direction}-{size}.

property

The property specifies the type of spacing to apply to the element. There are two possible values:

  • m – applies a margin.
  • p – applies padding.

direction

The direction indicates the margin or padding direction to apply the spacing. There are nine available directions in Vuetify:

  • t – applies the spacing for the margin-top or padding-top CSS properties of the element.
  • b – applies the spacing for margin-bottom or padding-bottom.
  • l – applies the spacing for margin-left or padding-left.
  • r – applies the spacing for margin-right or padding-right.
  • s – When Vuetify is in the default LTR mode, s acts similar to l. But in RTL mode, it behaves like r.
  • e – When Vuetify is in the default LTR mode, e acts similar to r. But in RTL mode, it behaves like l.
  • x – applies the spacing for both *-left and *-right.
  • y – applies the spacing for both *-top and *-bottom.
  • a – applies the spacing for the property in all four directions.
The specifiable directions for the Vuetify spacing helper classes.

size

The size sets the actual value of the spacing in pixels. A size 0 will remove the margin or padding from the element in the specified direction. To get the number of pixels for positive values, simply multiply the size number by 4px. Vuetify provides 16 possible positive spacing values:

  • 1 – sets the margin or padding to 4px.
  • 2 – sets the margin or padding to 8px.
  • 3 – sets the margin or padding to 12px.
  • 4 – sets the margin or padding to 16px.
  • 5 – sets the margin or padding to 20px.
  • 6 – sets the margin or padding to 24px.
  • 7 – sets the margin or padding to 28px.
  • 8 – sets the margin or padding to 32px.
  • 9 – sets the margin or padding to 36px.
  • 10 – sets the margin or padding to 40px.
  • 11 – sets the margin or padding to 44px.
  • 12 – sets the margin or padding to 48px.
  • 13 – sets the margin or padding to 52px.
  • 14 – sets the margin or padding to 56px.
  • 15 – sets the margin or padding to 60px.
  • 16 – sets the margin or padding to 64px.

We can specify negative spacing values by prefixing the number with an n. To get the number of pixels for negative values, multiply the size by -4px. Negative spacing values only apply to margins, and there are also 16 of them in Vuetify:

  • n1 – sets the margin to -4px.
  • n2 – sets the margin to -8px.
  • n3 – set the margin to -12px.
  • n4 – sets the margin to -16px.
  • n5 – sets the margin to -20px.
  • n6 – sets the margin to -24px.
  • n7 – sets the margin to -28px.
  • n8 – sets the margin to -32px.
  • n9 – sets the margin to -36px.
  • n10 – sets the margin to -40px.
  • n11 – sets the margin to -44px.
  • n12 – sets the margin to -48px.
  • n13 – sets the margin to -52px.
  • n14 – sets the margin to -56px.
  • n15 – sets the margin to -60px.
  • n16 – sets the margin to -64px.

Apart from the above available spacing values, we also have the auto spacing, which sets margins or paddings of elements to the auto value.

Examples

Now that we know the Vuetify spacing helper classes, let’s see how to use them in practice.

<template>
  <v-app>
    <v-row>
      <v-col sm="6"> <v-card color="blue" dark>JavaScript</v-card> </v-col>
      <v-col sm="6"> <v-card color="green" dark>PHP</v-card></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>

Here we’ve created two cards and customized their colors:

Two cards with customized colors.

Let’s add the mt-2 class to the v-row element containing the cards:

<template>
  <v-app>
    <v-row class="mt-2">
      <v-col sm="6"> <v-card color="blue" dark>JavaScript</v-card> </v-col>
      <v-col sm="6"> <v-card color="green" dark>PHP</v-card></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>

If you understood everything we covered previously, you’ll know that the mt-2 class will set the top margin of the v-row to 8px. When you run this code, you’ll see that there’s now some spacing between the two cards and the top of the page:

With the mx-3 class we’ll also create left and right margins (of 12px):

<template>
  <v-app>
    <v-row class="mt-2 mx-3">
      <v-col sm="6"> <v-card color="blue" dark>JavaScript</v-card> </v-col>
      <v-col sm="6"> <v-card color="green" dark>PHP</v-card></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Using Vuetify margin helper classes to add left and right margins of 12px.

And then, we’ll use the pa-4 and pa-6 classes to add paddings of different sizes to the two cards:

<template>
  <v-app>
    <v-row class="mt-2 mx-3">
      <v-col sm="6">
        <v-card color="blue" dark class="pa-4">JavaScript</v-card>
      </v-col>
      <v-col sm="6">
        <v-card color="green" dark class="pa-6">PHP</v-card></v-col
      >
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Adding paddings of different sizes to the cards with a Vuetify padding helper class.

Here’s another example. We have two buttons, whose colors we’ve set to green and red:

<template>
  <v-app>
    <v-col>
      <v-btn color="green" dark>Okay</v-btn>
      <v-btn color="red" dark>Cancel</v-btn></v-col
    >
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Two green and red Vuetify buttons.

The py-10 class will add a bottom and top padding of 40px to the green button:

<template>
  <v-app>
    <v-col>
      <v-btn color="green" class="py-10" dark>Okay</v-btn>
      <v-btn color="red" dark>Cancel</v-btn></v-col
    >
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Adding padding to the green button with a Vuetify padding helper class.

To space out the buttons, we’ll add a left margin to the Cancel button with the ml-5 class:

<template>
  <v-app>
    <v-col>
      <v-btn color="green" class="py-10" dark>Okay</v-btn>
      <v-btn color="red" dark class="ml-5">Cancel</v-btn></v-col
    >
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Spacing out the buttons with a Vuetify margin helper class.

We’ll also pad it horizontally with the px-16 class:

<template>
  <v-app>
    <v-col>
      <v-btn color="green" class="py-10" dark>Okay</v-btn>
      <v-btn color="red" dark class="ml-5 px-16">Cancel</v-btn></v-col
    >
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Padding the "Cancel" button with the Vuetify padding helper class.

Let’s add a negative right margin to the Okay button to remove the spacing we added:

<template>
  <v-app>
    <v-col>
      <v-btn color="green" class="py-10 mr-n5" dark>Okay</v-btn>
      <v-btn color="red" dark class="ml-5 px-16">Cancel</v-btn></v-col
    >
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Using a Vuetify negative margin helper class to remove the spacing between the buttons.

Conclusion

Vuetify provides spacing helper classes to allow us to space out and pad our UI elements without using custom classes or inline CSS. These classes can alter the margins or paddings of the elements in different directions and to various sizes.

Vuetify Select: How to Create Dropdown Lists with Vuetify

Dropdown lists are useful for getting user input from a known group of options, e.g., selecting a country among all the countries in the world, or choosing the hour of the day for an alarm. There are also known as select fields. In this article, we’re going to learn how use the Vuetify Select component to start creating dropdown lists in our apps.

The v-select Component

Vuetify provides the v-select component for creating select fields:

<template>
  <v-app>
    <v-row justify="center">
      <v-col sm="6"><v-select></v-select></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A Vuetify select field.

Vuetify Select Field Labels

We can describe a dropdown list with the label prop of v-select. We are going to be display a list of colors, so let’s label it “Color”:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"><v-select label="Color"></v-select></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A Vuetify select field with a label.

Vuetify Select Field Items

There are not options to select from in the dropdown list yet. Here’s what shows up when you click it:

No data available.

We can add items by assigning an array to the items prop. The items will be a group of colors.

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select label="Color" :items="items"></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>

Now there are options in the dropdown list.

A dropdown list with options.

We can now choose one of the options:

Choosing one of the options from the dropdown list.

Vuetify Select Set Default Value

To set a default value for a dropdown list, we can use v-model to create a two-way binding between the current value of the dropdown list and a variable. The initial value of this variable will be the default value of the select field:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select
          label="Color"
          :items="items"
          v-model="defaultSelection"
        ></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    defaultSelection: 'Yellow',
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
Setting a default value for a Vuetify select field.

Vuetify Select Field Filled Variant

We can set an alternative filled variant for a select field with the filled prop:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select label="Color" :items="items" filled></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
Vuetify select field field variant.

Vuetify Select Field Outlined Variant

We can also use an alternative outlined style, by setting the outlined prop of v-select to true:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select label="Color" :items="items" outlined></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
Vuetify select outlined variant.

Vuetify Select Field Solo Variant

We can use the solo variant with the solo prop:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select label="Color" :items="items" solo></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>

Dense Select Fields

Setting the dense prop to true on a v-select will compact the dropdown list:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select label="Color" :items="items" outlined dense></v-select
      ></v-col>
      <v-col sm="6"
        ><v-select label="Color" :items="items" solo dense></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
Dense dropdown lists.

Disabled Select Fields

To prevent interactivity with a select field, use the disabled prop:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select label="Color" :items="items" disabled></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
A disabled Vuetify select field.

Select Field Icons

The prepend-icon prop allows us to prepend an icon to a dropdown list. Here we’re displaying a palette icon to represent color:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select
          label="Color"
          :items="items"
          prepend-icon="mdi-palette"
        ></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
Using the v-select prepend-icon prop.

Similarly, we can use the append-icon prop to append an icon to a select field:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select
          label="Color"
          :items="items"
          append-icon="mdi-palette"
        ></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
Using the v-select append-icon prop.

Multi Select Dropdown Lists in Vuetify

In instances where we want users to be able to select more than one option, we can use the multiple prop

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select
          label="Color"
          :items="items"

          multiple
        ></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
Selecting two options in a dropdown list.
Selecting two options in a dropdown list.
The dropdown list options are comma-separated.
The options are comma-separated.

Displaying Chips in Multi Select Dropdown Lists

We can display the options as a group of chips instead of comma-separated values. We do this with the chips prop:

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select
          label="Color"
          :items="items"

          multiple
          chips
        ></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
Displaying chips in multi select dropdown lists.

Customizing Select Field Menu Props

We can customize certain properties of the menu that pops up when the dropdown list is clicked. Modifiable properties include top, bottom, offsetX and offsetY.

<template>
  <v-app>
    <v-row justify="center" class="ma-2">
      <v-col sm="6"
        ><v-select
          label="Color"
          :items="items"
          :menu-props="{ offsetX: true }"
        ></v-select
      ></v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: ['Blue', 'Red', 'Yellow', 'Green'],
  }),
};
</script>
Customizing select field menu props.

Summary

Dropdown lists come in handy when we want to provide a finite list of known options to the user to choose from. Vuetify provides the v-select component to create and customize them in diverse ways.

Vuetify Data Table: How to Create Data Tables

A table is a great way of presenting structured information in an easily understandable format. In this post, we’re going to learn how to use the Vuetify data table component, which is used for displaying tabular data and comes with useful features such as sorting, searching, pagination, and more.

The Vuetify Data Table Component (v-data-table)

Vuetify provides the v-data-table component for creating data tables. The headers prop of this component is an array of objects used to configure the data table headers. Each object in this array has a text property, which determines the header name that shows up for a particular column. We also pass an array of objects (desserts) to the items prop. Each object in desserts corresponds to a row in the data table, and each property represents a table cell for that row. The property names of these objects have to match one of the value property values of the objects in the headers array, i.e. (a key name must be one of name, calories, fat, carbs, protein, and iron).

We use the items-per-page property to paginate the data table. Here we set it to 5, so we have 2 pages for the 10 desserts.

<template>
  <v-app>
    <v-data-table
      :headers="headers"
      :items="desserts"
      :items-per-page="5"
      class="elevation-1"
    ></v-data-table>
  </v-app>
</template>
<script>
export default {
  data() {
    return {
      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%',
        },
      ],
    };
  },
};
</script>

And here’s our table:

A Vuetify data table created with the v-data-table component.

Vuetify Data Table Dense

Setting the dense prop makes a data table more compact, as the name implies:

<template>
  <v-app>
    <v-data-table
      dense
      :headers="headers"
      :items="desserts"
      item-key="name"
      class="elevation-1"
    ></v-data-table>
  </v-app>
</template>
<script>
export default {
  data: () => ({
    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%',
      },
    ],
    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' },
    ],
  }),
};
</script>
A dense Vuetify data table.

Vuetify Data Table Search Features

We can filter data on the data table with the search prop. Here, we’re binding whatever value entered in the text field with the input used for searching the table:

<template>
  <v-app>
    <v-card>
      <v-card-title>
        Nutrition
        <v-spacer></v-spacer>
        <v-text-field
          v-model="search"
          append-icon="mdi-magnify"
          label="Search"
          single-line
          hide-details
        ></v-text-field>
      </v-card-title>
      <v-data-table
        :headers="headers"
        :items="desserts"
        :search="search"
        :items-per-page="5"
      ></v-data-table>
    </v-card>
  </v-app>
</template>
<script>
export default {
  data: () => ({
    search: '',
    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%',
      },
    ],
    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' },
    ],
  }),
};
</script>
Add search features to a Vuetify data table component.

Vuetify Data Table Custom Filters

We can specify our custom filter function by passing a method to the custom-filter prop that has the signature (value: any, search: string | null, item: any) => boolean.

<template>
  <v-app>
    <div>
      <v-data-table
        :headers="headers"
        :items="desserts"
        item-key="name"
        class="elevation-1"
        :search="search"
        :custom-filter="filterOnlyCapsText"
        :items-per-page="5"
      >
        <template v-slot:top>
          <v-text-field
            v-model="search"
            label="Search (UPPER CASE ONLY)"
            class="mx-4"
          ></v-text-field>
        </template>
      </v-data-table>
    </div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data() {
    return {
      search: '',
      calories: '',
      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%',
        },
      ],
    };
  },
  computed: {
    headers() {
      return [
        {
          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' },
      ];
    },
  },
  methods: {
    filterOnlyCapsText(value, search, item) {
      return (
        value != null &&
        search != null &&
        typeof value === 'string' &&
        value.toString().toLocaleUpperCase().indexOf(search) !== -1
      );
    },
  },
};
</script>
Add custom filters with the custom-filter prop of the Vuetify data table component.

We can also customize the filtering of a specific column by supplying a function to the filter property on an item in the array passed to the headers prop. In the code example below, we add a text field below the rows of the data table (with the body.append slot) which can be used to display all the desserts with calories less than a certain value.

<template>
  <v-app>
    <div>
      <v-data-table
        :headers="headers"
        :items="desserts"
        item-key="name"
        class="elevation-1"
        :search="search"
        :custom-filter="filterOnlyCapsText"
        :items-per-page="5"
      >
        <template v-slot:top>
          <v-text-field
            v-model="search"
            label="Search (UPPER CASE ONLY)"
            class="mx-4"
          ></v-text-field>
        </template>
        <template v-slot:body.append>
          <tr>
            <td></td>
            <td>
              <v-text-field
                v-model="calories"
                type="number"
                label="Less than"
              ></v-text-field>
            </td>
            <td colspan="4"></td>
          </tr>
        </template>
      </v-data-table>
    </div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data() {
    return {
      search: '',
      calories: '',
      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%',
        },
      ],
    };
  },
  computed: {
    headers() {
      return [
        {
          text: 'Dessert (100g serving)',
          align: 'start',
          sortable: false,
          value: 'name',
        },
        {
          text: 'Calories',
          value: 'calories',
          filter: (value) => {
            return this.calories ? value < parseInt(this.calories) : true;
          },
        },
        { text: 'Fat (g)', value: 'fat' },
        { text: 'Carbs (g)', value: 'carbs' },
        { text: 'Protein (g)', value: 'protein' },
        { text: 'Iron (%)', value: 'iron' },
      ];
    },
  },
  methods: {
    filterOnlyCapsText(value, search, item) {
      return (
        value != null &&
        search != null &&
        typeof value === 'string' &&
        value.toString().toLocaleUpperCase().indexOf(search) !== -1
      );
    },
  },
};
</script>
Customizing the filtering of a specific column of the Vuetify data table component.

Vuetify Data Table Filterable

We can prevent specific columns from being included when searching through the table rows by setting the filterable property to false on the element of the array passed to headers that is associated with the column. In the code example below, we’ve turned off searching for the dessert name column:

<template>
  <v-app>
    <v-card class="ma-4">
      <v-card-title>
        <v-text-field
          v-model="search"
          append-icon="mdi-magnify"
          label="Search"
          single-line
          hide-details
        ></v-text-field>
      </v-card-title>
      <v-data-table
        :headers="headers"
        :items="desserts"
        :search="search"
        :items-per-page="5"
      ></v-data-table>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      search: '',
      headers: [
        {
          text: 'Dessert (100g serving)',
          align: 'start',
          filterable: 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%',
        },
      ],
    };
  },
};
</script>
Using the filterable prop of the Vuetify data table component.

By default, the data table component displays a default footer using the v-data-footer component. We can pass props to this component with the footer-props prop of v-data-table:

<template>
  <v-app>
    <v-data-table
      :headers="headers"
      :items="desserts"
      :items-per-page="5"
      item-key="name"
      class="elevation-1 ma-4"
      :footer-props="{
        showFirstLastPage: true,
        firstIcon: 'mdi-arrow-collapse-left',
        lastIcon: 'mdi-arrow-collapse-right',
        prevIcon: 'mdi-minus',
        nextIcon: 'mdi-plus',
      }"
    ></v-data-table>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      headers: [
        {
          text: 'Dessert (100g serving)',
          align: 'start',
          value: 'name',
        },
        { text: 'Category', value: 'category' },
      ],
      desserts: [
        {
          name: 'Frozen Yogurt',
          category: 'Ice cream',
        },
        {
          name: 'Ice cream sandwich',
          category: 'Ice cream',
        },
        {
          name: 'Eclair',
          category: 'Cookie',
        },
        {
          name: 'Cupcake',
          category: 'Pastry',
        },
        {
          name: 'Gingerbread',
          category: 'Cookie',
        },
        {
          name: 'Jelly bean',
          category: 'Candy',
        },
        {
          name: 'Lollipop',
          category: 'Candy',
        },
        {
          name: 'Honeycomb',
          category: 'Toffee',
        },
        {
          name: 'Donut',
          category: 'Pastry',
        },
        {
          name: 'KitKat',
          category: 'Candy',
        },
      ],
    };
  },
};
</script>
Customizing the v-data-table footer with the footer-props prop.

Conclusion

The Vuetify data table component (v-data-table) comes in handy for laying out data in a digestible format. We can not only display data but perform searching and other operations. It also allows UI customizations like making the table more compact and functional customizations such as specifying a custom filter function.

How to Use the Vuetify Checkbox Component

A checkbox allows a user to select between two values. They are useful for getting boolean input (true or false), perhaps checking off a task in a to-do list app to show completion or deciding whether or not to accept a license agreement during software installation. In this article, we’re going to learn how to create a checkbox in Vuetify.

The v-checkbox Component

Vuetify provides the v-checkbox component for creating a checkbox:

<template>
  <v-app>
    <v-row class="ma-2" justify="center">
      <v-checkbox></v-checkbox>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Creating a Vuetify checkbox with the v-checkbox component.

Clicking the checkbox will toggle its checked state:

Clicking the checkbox will toggle its value.

Setting a Checkbox value

Use the value prop to set the checked state of the checkbox.

<template>
  <v-app>
    <v-row class="ma-2" justify="center">
      <v-checkbox :value="true"></v-checkbox>
      <v-checkbox :value="false"></v-checkbox>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Setting a checkbox value.

Vuetify Checkbox Labels

We can label a Vuetify checkbox with the label prop:

<template>
  <v-app>
    <v-row class="ma-2" justify="center">
      <v-checkbox v-model="checked" label="Coding Beauty"></v-checkbox>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    checked: false,
  }),
};
</script>
Setting a label for a Vuetify checkbox.

Vuetify Checkbox Label Slot

To include HTML content in a checkbox label, we can put it in the label slot:

<template>
  <v-app>
    <v-row class="ma-2" justify="space-around">
      <v-checkbox color="indigo" input-value="true">
        <template v-slot:label>
          Visit the&nbsp;
          <a
            target="_blank"
            href="https://codingbeautydev.com"
            @click.stop
            v-on="on"
          >
            Coding Beauty website
          </a>
        </template>
      </v-checkbox>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Including HTML content in a Vuetify checkbox with the label slot.

Vuetify Checkbox Boolean v-model

To control the current value of the checkbox, we can use v-model to create a two-way binding between the v-checkbox and a boolean variable.

Here, we create a checkbox and a button below it to toggle the state of the checkbox. We indicate this state with some text in the label prop.

<template>
  <v-app>
    <div class="ma-2 d-flex justify-center">
      <v-checkbox v-model="checked" :label="`Checked: ${checked}`"></v-checkbox>
    </div>
    <div class="ma-2 d-flex justify-center">
      <v-btn color="indigo" dark @click="checked = !checked">{{
        checked ? 'Uncheck' : 'Check'
      }}</v-btn>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    checked: false,
  }),
};
</script>

Clicking the button will negate checked, and this will reflect on the checkbox and its label:

Using a boolean v-model on the Vuetify checkbox component.

Vuetify Checkbox Array v-model

We can pass an array to v-model to allow multiple checkbox components to share the same variable used for the two-way binding:

<template>
  <v-app>
    <v-container fluid>
      <p>Selected: {{ selected }}</p>
      <v-checkbox
        v-model="selected"
        label="JavaScript"
        value="javascript"
      ></v-checkbox>
      <v-checkbox
        v-model="selected"
        label="TypeScript"
        value="typescript"
      ></v-checkbox>
    </v-container>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selected: [],
  }),
};
</script>
Padding an array v-model to the checkbox components.

Customizing Checkbox Color in Vuetify

The color prop allows us to set the color of the checkbox background when checked:

<template>
  <v-app>
    <v-row justify="space-around" class="ma-4">
      <v-checkbox color="primary" label="primary"></v-checkbox>
      <v-checkbox color="green" label="green"></v-checkbox>
      <v-checkbox color="yellow darken-3" label="yellow darken-3"></v-checkbox>
      <v-checkbox color="red" label="red"></v-checkbox>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Customizing checkbox color in Vuetify.

Disabled Checkbox

We can turn off checkbox interactivity with the disabled prop. It will no longer accept input when disabled.

<template>
  <v-app>
    <v-row class="ma-2" justify="space-around">
      <v-checkbox
        label="on disabled"
        color="green"
        input-value="true"
        disabled
      ></v-checkbox>
      <v-checkbox
        label="off disabled"
        color="green"
        disabled
      ></v-checkbox>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Disabled Vuetify checkboxes.

Indeterminate Checkbox

We can make the checkbox indeterminate by using the indeterminate prop on the v-checkbox:

<template>
  <v-app>
    <v-row class="ma-2" justify="space-around">
      <v-checkbox label="indeterminate" color="red" indeterminate></v-checkbox>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
An indeterminate Vuetify checkbox.

Summary

We can use a checkbox when we need to accept boolean input. Vuetify provides the v-checkbox component to create it and provides various props for customization.

Vuetify List: How to Create Lists with Vuetify

Lists are used to display a group of related information. This information might be dynamic and modifiable by the user (e.g., a list of contacts or tasks) or it might be static (like a list of links for navigating around an app). Lists provide a consistent styling for a group of text or images. In this article, we’re going to learn how to add lists to our UI using the Vuetify list component.

The v-list Component

The names of the components for creating lists in Vuetify are quite self-explanatory. The v-list component is for creating lists. We use the v-list-item component to create an additional item in the list. v-list-item-content contains the primary list content, and v-list-item-title displays the list title. For example:

<template>
  <v-app>
    <v-card class="mx-auto ma-4">
      <v-list>
        <v-list-item
          v-for="i in 5"
          :key="i"
        >
          <v-list-item-content>
            <v-list-item-title>
              List Item {{ i }}
            </v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Using the Vuetify list component.

Vuetify List Two Line

Vuetify lists are single-line by default. To display two lines of content in a list, we set the two-line prop to true:

<template>
  <v-app>
    <v-card class="mx-auto ma-4">
      <v-list>
        <v-list-item
          v-for="i in 5"
          :key="i"
          two-line
        >
          <v-list-item-content>
            <v-list-item-title>
              List Item
            </v-list-item-title>
            <v-list-item-subtitle>
              Subtitle
            </v-list-item-subtitle>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Using the two-line prop of the Vuetify list component.

Vuetify List Three Line

We can also display three lines of text in a list with the three-line prop:

<template>
  <v-app>
    <v-card class="mx-auto ma-4">
      <v-list>
        <v-list-item
          v-for="i in 5"
          :key="i"
          three-line
        >
          <v-list-item-content>
            <v-list-item-title>
              List Item
            </v-list-item-title>
            <v-list-item-subtitle>
              Subtitle 1
            </v-list-item-subtitle>
            <v-list-item-subtitle>
              Subtitle 2
            </v-list-item-subtitle>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Using the three-line prop of the Vuetify list component.

Vuetify List Item Groups

We can use the v-list-item-group component in a list to create a group of selectable list items.

<template>
  <v-app>
    <v-card class="mx-auto ma-4" width="300">
      <v-list>
        <v-list-item-group v-model="selectedItem" color="primary">
          <v-list-item v-for="(item, i) in items" :key="i">
            <v-list-item-icon
              ><v-icon v-text="item.icon"></v-icon
            ></v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selectedItem: 1,
    items: [
      { text: 'Contacts', icon: 'mdi-account' },
      { text: 'Recent', icon: 'mdi-clock' },
      { text: 'Starred', icon: 'mdi-star' },
      { text: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
A selectable Vuetify list created with the list item group component.

The list maintains state, and clicking another list item will change the selection:

Changing the selected item of the list.

Dense Lists

We can compact lists in Vuetify with the dense prop:

<template>
  <v-app>
    <v-card class="mx-auto ma-4" width="300">
      <v-list dense>
        <v-list-item-group v-model="selectedItem" color="primary">
          <v-list-item v-for="(item, i) in items" :key="i">
            <v-list-item-icon
              ><v-icon v-text="item.icon"></v-icon
            ></v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selectedItem: 1,
    items: [
      { text: 'Contacts', icon: 'mdi-account' },
      { text: 'Recent', icon: 'mdi-clock' },
      { text: 'Starred', icon: 'mdi-star' },
      { text: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
Using the dense prop.

Disabled Lists

We can disable interaction with a list by setting the disabled prop to true:

<template>
  <v-app>
    <v-card class="mx-auto ma-4" width="300">
      <v-list disabled>
        <v-list-item-group v-model="selectedItem" color="primary">
          <v-list-item v-for="(item, i) in items" :key="i">
            <v-list-item-icon
              ><v-icon v-text="item.icon"></v-icon
            ></v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selectedItem: 1,
    items: [
      { text: 'Contacts', icon: 'mdi-account' },
      { text: 'Recent', icon: 'mdi-clock' },
      { text: 'Starred', icon: 'mdi-star' },
      { text: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>

Flat Lists

The flat prop removes the background color of the selected list item:

<template>
  <v-app>
    <v-card class="mx-auto ma-4" width="300">
      <v-list flat>
        <v-list-item-group v-model="selectedItem" color="primary">
          <v-list-item v-for="(item, i) in items" :key="i">
            <v-list-item-icon
              ><v-icon v-text="item.icon"></v-icon
            ></v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selectedItem: 1,
    items: [
      { text: 'Contacts', icon: 'mdi-account' },
      { text: 'Recent', icon: 'mdi-clock' },
      { text: 'Starred', icon: 'mdi-star' },
      { text: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
A flat Vuetify list.

Vuetify List Nav Styling

Setting the nav prop to true on a v-list reduces the width and rounds the corners of the v-list-items in it:

<template>
  <v-app>
    <v-card class="mx-auto ma-4" width="300">
      <v-list nav>
        <v-list-item-group v-model="selectedItem" color="green">
          <v-list-item v-for="(item, i) in items" :key="i">
            <v-list-item-icon
              ><v-icon v-text="item.icon"></v-icon
            ></v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selectedItem: 1,
    items: [
      { text: 'Contacts', icon: 'mdi-account' },
      { text: 'Recent', icon: 'mdi-clock' },
      { text: 'Starred', icon: 'mdi-star' },
      { text: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
A Vuetify list with the nav styling.

Rounded List Items in Vuetify

We can make the v-list-items inside a v-list fully rounded by setting the rounded prop to true:

<template>
  <v-app>
    <v-card class="mx-auto ma-4" width="300">
      <v-list rounded>
        <v-list-item-group v-model="selectedItem" color="indigo">
          <v-list-item v-for="(item, i) in items" :key="i">
            <v-list-item-icon
              ><v-icon v-text="item.icon"></v-icon
            ></v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selectedItem: 1,
    items: [
      { text: 'Contacts', icon: 'mdi-account' },
      { text: 'Recent', icon: 'mdi-clock' },
      { text: 'Starred', icon: 'mdi-star' },
      { text: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
A Vuetify list with rounded list items.

Shaped List Items in Vuetify

Lists with the shaped prop set to true have rounded borders on one side of the v-list-items:

<template>
  <v-app>
    <v-card class="mx-auto ma-4" width="300">
      <v-list shaped>
        <v-list-item-group v-model="selectedItem" color="red accent-2">
          <v-list-item v-for="(item, i) in items" :key="i">
            <v-list-item-icon
              ><v-icon v-text="item.icon"></v-icon
            ></v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selectedItem: 1,
    items: [
      { text: 'Contacts', icon: 'mdi-account' },
      { text: 'Recent', icon: 'mdi-clock' },
      { text: 'Starred', icon: 'mdi-star' },
      { text: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
A Vuetify list with shaped list items.

Vuetify List Sub Groups

With the v-list-group component and its sub-group prop we can create sub groups of up to two levels in depth:

<template>
  <v-app>
    <v-card class="mx-auto ma-4" width="300">
      <v-list>
        <v-list-group :value="true" prepend-icon="mdi-file">
          <template v-slot:activator>
            <v-list-item-title>Files</v-list-item-title>
          </template>
          <v-list-group :value="true" no-action sub-group>
            <template v-slot:activator>
              <v-list-item-content>Books</v-list-item-content>
            </template>

            <v-list-item v-for="(book, i) in books" :key="i" link>
              <v-list-item-title v-text="book"></v-list-item-title>
              <v-list-item-icon><v-icon>mdi-book</v-icon></v-list-item-icon>
            </v-list-item>
          </v-list-group>
          <v-list-group no-action sub-group>
            <template v-slot:activator>
              <v-list-item-content>Code</v-list-item-content>
            </template>

            <v-list-item v-for="(code, i) in codes" :key="i" link>
              <v-list-item-title v-text="code"></v-list-item-title>
              <v-list-item-icon><v-icon>mdi-xml</v-icon></v-list-item-icon>
            </v-list-item>
          </v-list-group>
        </v-list-group>
        <v-list-item>
          <v-list-item-icon><v-icon>mdi-cog</v-icon></v-list-item-icon>
          <v-list-item-title>Settings</v-list-item-title>
        </v-list-item>
      </v-list>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    selectedItem: 1,
    books: ['History', 'Fiction', 'Philosophy'],
    codes: ['C#', 'JavaScript', 'PHP'],
  }),
};
</script>
A Vuetify list with sub groups.

We can expand and contract the sub groups as needed:

Expanding and contracting sub groups in the list.

Summary

Lists are used to present a group of information that are related in some way. Vuetify provides v-list, v-list-group, v-list-item and other components for creating and customizing lists.