Home

Input TextField with DatePicker using Vuetify(supports Tab and click operations)

In vuetify creating a DatePicker is an easy task, but attaching it to a input field, adding collapse and expand feature to it needs some work. In this post we're going to learn how to link DatePicker to TextField with a smooth user experience.

Starting with a Date Picker

We start with implementing a minimal date picker from vuetify. The dateValue is binded to the DatePicker.

<template>
  <v-layout row wrap>
    <v-date-picker locale="en-in" v-model="dateValue" no-title></v-date-picker>
  </v-layout>
</template>
<script>
export default {
  data() {
    return {
      dateValue: null,
    };
  },
};
</script>

Linking TextField to DatePicker

Then add a readonly text input field which get its value from dateValue

<template>
  <v-container>
    <v-text-field
      :label="label"
      readonly
      prepend-icon="event"
      :value="dateValue"
    ></v-text-field>
    <v-date-picker locale="en-in" v-model="dateValue" no-title></v-date-picker>
  </v-container>
</template>
<script>
export default {
  data() {
    return {
      dateValue: null,
    };
  },
  props: {
    label: String,
  },
};
</script>

Showing/Hiding DatePicker when TextField is clicked

Having the basic functionality required, now we want to hide the date picker, and selectively display it when the text field is clicked. For this we use the v-menu component of vuetify.

<template>
  <v-menu
    v-model="dateMenu"
    :close-on-content-click="false"
    :nudge-right="40"
    lazy
    transition="scale-transition"
    offset-y
    full-width
    min-width="290px"
    max-width="290px"
  >
    <template v-slot:activator="{on}">
      <v-text-field
        :label="label"
        prepend-inner-icon="event"
        readonly
        hide-details
        :value="dateValue"
        v-on="on"
      ></v-text-field>
    </template>
    <v-date-picker
      locale="en-in"
      v-model="dateValue"
      no-title
      @input="dateMenu = false"
    ></v-date-picker>
  </v-menu>
</template>
<script>
export default {
  data() {
    return {
      dateMenu: false,
      dateValue: null,
    };
  },
  props: {
    label: String,
  },
};
</script>

We have the entire functionality that we want, but we still lack the keyboard accessibility

Keyboard Accessibility

You can listen for the focus and blur events to enhance the experience for the users who prefer to navigate using keyboard (using Tab key). Therefore the final code considering the focus and blur of text input field will be as follows:

The setTimeout was used in this code, since the value of dateValue was set after the transition was completed in usual case. I assume the delay of 200ms for the transition.

<template>
  <v-menu
    v-model="dateMenu"
    :close-on-content-click="false"
    :nudge-right="40"
    lazy
    transition="scale-transition"
    offset-y
    full-width
    min-width="290px"
    max-width="290px"
  >
    <template v-slot:activator="{on}">
      <v-text-field
        :label="label"
        prepend-inner-icon="event"
        readonly
        hide-details
        :value="dateValue"
        v-on="on"
        @focus="focusDate"
        @blur="blurDate"
      ></v-text-field>
    </template>
    <v-date-picker
      locale="en-in"
      v-model="dateValue"
      no-title
      @input="dateMenu = false"
    ></v-date-picker>
  </v-menu>
</template>
<script>
export default {
  data() {
    return {
      dateMenu: false,
      dateValue: null,
    };
  },
  props: {
    label: {
      type: String,
      required: true,
    },
  },
  methods: {
    focusDate() {
      setTimeout(() => {
        if (!this.dateMenu) {
          this.dateMenu = true;
        }
      }, 200);
    },
    blurDate() {
      setTimeout(() => {
        if (this.dateMenu) {
          this.dateMenu = false;
        }
      }, 200);
    },
  },
};
</script>

Resources:

This post is inspired by this article and this answer



Last Updated on

Next Post: GraphProtocol: TS2322 null assignment in Subgraph →

Comments