Tari Ibaba

Tari Ibaba is a software developer with years of experience building websites and apps. He has written extensively on a wide range of programming topics and has created dozens of apps and open-source libraries.

Vuetify Alert: How to Notify Users with Alerts

We use an alert to pass on important information to users by using contextual icons and colors. The icon and color match the type of message it conveys to the user. In this article, we’re going to learn how to create and customize alert notifications with the Vuetify alert component.

The Vuetify Alert Component (v-alert)

Vuetify provides the v-alert component for creating alerts:

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-alert> Alert Component </v-alert>
    </div>
  </v-app>
</template>

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

Using v-alert without any props creates a simple alert containing the text, without any color, border or icon:

A simple Vuetify alert component.

Vuetify Alert Colors

The color prop of v-alert allows us to customize the color of an alert component.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert color="indigo" dark> Alert Component </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Customizing the color of the Vuetify alert component.

Vuetify Alert Border

The border prop adds a border to one of the 4 sides of the alert. They are four possible values for each of the sides: top, bottom, left, and right.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert border="top" color="red lighten-2" dark>
          I'm an alert with a top border and red color
        </v-alert>
        <v-alert border="right" color="green" dark>
          I'm an alert with a right border and green color
        </v-alert>
        <v-alert border="bottom" color="pink darken-1" dark>
          I'm an alert with a bottom border and pink color
        </v-alert>
        <v-alert border="left" color="indigo" dark>
          I'm an alert with a left border and indigo color
        </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Alert components with borders.

Vuetify Alert Colored Border

The colored-prop will remove the alert background in order to emphasize the border, whose color is set to the value of the color prop:

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert border="left" color="indigo" colored-border elevation="2">
          An alert with a colored border
        </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
An alert with a colored border.

Dense Alert

Setting the dense prop to true on the v-alert will make it more compact by decreasing its height.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert dense type="info">
          Dense alert of type info
        </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

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

When a border is set, the border thickness will be decreased to stay consistent with the dense style:

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert dense type="info" border="right">
          Dense alert of type info
        </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
A dense alert with a border.

Vuetify Alert Dismissable

The dimissable prop adds a close icon button at the end of the alert component.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert border="top" color="green" dismissible dark>
          Dismissable alert
        </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

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

Clicking the close button will set the alert value to false, which will hide the alert:

The alert is no longer visible.

Vuetify Alert v-model

We can also directly control the visibility of the alert from code by using v-model to create a two-way binding between a variable and the alert value.

To see how to do this in practice, let’s create a button below the now hidden alert from our previous code sample. We’ll also set up the two-way binding between an alert variable and the visibility of the alert.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert border="top" color="green" dismissible dark v-model="alert">
          Dismissable alert
        </v-alert>
      </v-col>
    </div>
    <div class="d-flex justify-center ma-4">
      <v-btn color="primary" @click="alert = true">Reset</v-btn>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    alert: true,
  }),
};
</script>
A button below the now hidden alert.
A button below the now hidden alert.

Clicking the button will set alert to true, which will restore the visibility of the alert.

Restoring the alert visibility.
Restoring the visibility of the alert.

Alert Icons

We can include an icon at the beginning of an alert with the icon prop.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert border="top" color="red accent-2" dark icon="mdi-star">
          An alert with an icon
        </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
An alert with an icon.

Vuetify Alert Elevation

We can customize the amount of elevation an alert component has using the elevation prop. This prop can take any value between 0 and 24.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert border="top" color="orange" colored-border elevation="5">
          Elevated alert
        </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
An alert with elevation.

Vuetify Alert Outlined

Setting the outlined prop to true will display the outlined variant of an alert. This outlined style makes the alert background transparent and sets the color of its border and text to the value of the color prop.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert color="green" outlined> Outlined alert </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
An outlined alert.

Vuetify Alert Prominent

The prominent prop makes the alert more pronounced by increasing the height and applying a halo to the icon:

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert color="red accent-2" prominent icon="mdi-school" dark>
          Prominent alert
        </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

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

Text Alert

The text alert variant has a reduced background opacity. We can set an alert to this alternative style with the text prop:

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert color="teal" text> Text alert </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

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

Vuetify Alert Shaped

Setting the shaped prop to true on an alert will add a border-radius at the top-left and bottom-right of the alert:

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert color="blue" shaped dark> Shaped alert </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

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

Vuetify Alert Custom Transitions

We can customize the transition an alert shows when toggling its visibility, using the transition prop. For example, in the code below we set the transition prop to scale-transition, which will make the alert display a scale transition when it is being hidden or shown.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-btn color="primary" @click="alert = !alert"> Toggle </v-btn>
    </div>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert
          color="indigo"
          dark
          transition="scale-transition"
          v-model="alert"
        >
          Shaped alert
        </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

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

Vuetify Alert Type

v-alert comes with a type prop which provides 4 styles that modify the icon and color of the alert. These styles are success, info, warning, and error.

<template>
  <v-app>
    <div class="d-flex justify-center ma-4">
      <v-col sm="6">
        <v-alert type="success"> I'm a success alert. </v-alert>
        <v-alert type="info"> I'm an info alert. </v-alert>
        <v-alert type="warning"> I'm a warning alert. </v-alert>
        <v-alert type="error"> I'm an error alert. </v-alert>
      </v-col>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Alert components of different types.

Summary

An alert is useful for conveying important information to our users using contextual icons and colors. Vuetify provides the v-alert component for creating and customizing alerts.

How to Use the Vuetify Chip Component

Chips are used to pass on small amounts of information to users. They can be interactive and perform certain actions when clicked like buttons, or we can use them to display selected data in a select field. In this article, we’ll learn how to create and customize chips with Vuetify.

The v-chip Component

Vuetify provides the v-chip component for creating a chip.

<template>
  <v-app>
    <v-row class="ma-4" justify="center">
      <v-chip>Chip Component </v-chip>
    </v-row>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>
The Vuetify chip component.

Closable Chip

We can make a chip closable by setting the close prop to true and listening for a @click:close event.

<template>
  <v-app>
    <v-row class="ma-4" justify="center">
      <v-chip v-if="chip1" class="ma-2" close @click:close="chip1 = false"
        >Chip 1</v-chip
      >
      <v-chip v-if="chip2" class="ma-2" close @click:close="chip2 = false"
        >Chip 2</v-chip
      >
      <v-chip v-if="chip3" class="ma-2" close @click:close="chip3 = false"
        >Chip 3</v-chip
      >
    </v-row>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    chip1: true,
    chip2: true,
    chip3: true,
  }),
};
</script>

In the code above, we’ve created three closable chips. Three variables control the visibility of the chips with v-if:

Three closable chips.

Clicking the close button of a chip, say “Chip 2”, will set its visibility variable to false and hide it:

Clicking the close button of a chip hides the chip.

Chip Colors

Like many Vuetify components, v-chip comes with the color prop, which we can use to customize its color. We can use any color from the Material Design palette.

<template>
  <v-app>
    <v-row class="ma-4" justify="center">
      <v-chip class="ma-2">Default</v-chip>
      <v-chip class="ma-2" color="green" dark>Green</v-chip>
      <v-chip class="ma-2" color="primary">Primary</v-chip>
      <v-chip class="ma-2" color="red" dark>Red</v-chip>
    </v-row>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>
Customizing the chip color.

Draggable Chips

To make a chip draggable, set the draggable prop of the v-chip to true:

<template>
  <v-app>
    <v-row class="ma-4" justify="center">
      <v-chip class="ma-2" draggable>Draggable</v-chip>
    </v-row>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>
A draggable chip.

Now it can be dragged around with the mouse:

The chip can be dragged with a mouse.

Active Chip Filters

The v-chip component comes with a filter prop that when set to true, will show an icon on the chip if the chip is active. You can make a chip active by setting its input-value prop to true:

<template>
  <v-app>
    <v-row class="ma-4" justify="center">
      <v-chip class="ma-2" filter :input-value="true">Active Chip</v-chip>
    </v-row>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>
An active chip.

The default icon is a checkmark, but we can customize it with the filter-icon prop.

<template>
  <v-app>
    <v-row class="ma-4" justify="center">
      <v-chip class="ma-2" filter :input-value="true" filter-icon="mdi-plus"
        >Active Chip</v-chip
      >
    </v-row>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>
Customizing the filter icon of the chip.

Label Chips

Setting the label prop to true on the v-chip will change its border-radius to that of a card component (v-card):

<template>
  <v-app>
    <v-row class="ma-4" justify="center">
      <v-chip class="ma-2" label>Label 1</v-chip>
      <v-chip class="ma-2" label color="yellow">Label 2</v-chip>
      <v-chip class="ma-2" label color="primary">Label 3</v-chip>
    </v-row>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>
Label chips

Button Chips

We can make a chip act like a button with the link prop:

<template>
  <v-app>
    <div class="d-flex justify-center align-center ma-4">
      <v-chip class="ma-2" link>
        Chip Component
      </v-chip>
    </div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>

Now the chip will visually respond and display a ripple when clicked.

The chip displays a ripple when clicked.

Removing the Ripple from a Chip

Setting the ripple prop to false will remove the ripple from a chip button.

<template>
  <v-app>
    <div class="d-flex justify-center align-center ma-4">
      <v-chip class="ma-2" link :ripple="false">
        Chip Component
      </v-chip>
    </div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>

Now a ripple doesn’t show when the chip button is clicked:

A ripple doesn't show when the chip is clicked.

Outlined Chips

We display the outlined variant of a chip by setting the outlined prop to true. Outlined chips inherit their border color from the current text color.

<template>
  <v-app>
    <v-row class="ma-4" justify="center">
      <v-chip class="ma-2" outlined color="green">Outlined 1</v-chip>
      <v-chip class="ma-2" outlined color="red">Outlined 2</v-chip>
      <v-chip class="ma-2" outlined color="indigo">Outlined 3</v-chip>
    </v-row>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>
Outlined chips.

Custom Chip Sizes

The v-chip component comes with props for customizing its size. They are x-small, small, large, and x-large.

<template>
  <v-app>
    <div class="d-flex justify-center align-center ma-4">
      <v-chip class="ma-2" x-small> x-small chip </v-chip>
      <v-chip class="ma-2" small> small chip </v-chip>
      <v-chip class="ma-2"> Default </v-chip>
      <v-chip class="ma-2" large> large chip </v-chip>
      <v-chip class="ma-2" x-large> x-large chip </v-chip>
    </div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>
Chips of different sizes.

Chip Icons

We can display any icon from the Material Icons font library in a chip:

<template>
  <v-app>
    <div class="d-flex justify-center align-center ma-4">
      <v-chip class="ma-2" color="primary">
        Premium
        <v-icon right> mdi-star </v-icon>
      </v-chip>
      <v-chip class="ma-2" color="green accent-4" dark>
        <v-icon left> mdi-checkbox-marked-circle </v-icon>
        Confirmed
      </v-chip>
      <v-chip class="ma-2">
        <v-icon left>mdi-alarm</v-icon>
        7:00 AM
      </v-chip>
    </div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
};
</script>
Displaying icons in a chip.

Summary

Chips are useful for conveying small pieces of information to users. Vuetify provides the v-chip component for creating a chip with various props for customization.

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.