Categories
Vue 3

How to Build a Datepicker Component with Vue.js 3?

Spread the love

Sometimes, we want to build our own date picker component in our Vue 3 app to let users select a date.

In this article, we’ll look at how to build a date picker component with Vue 3.

Build a Datepicker Component with Vue.js 3

We can build our own input component by creating a component that takes the modelValue prop and emits the update:modelValue event.

The 2 things together is the same as the v-model directive.

So we can write the following code to create a date picker and use it.

App.vue

<template>
  <DatePicker v-model="date" />
  <p>{{ date }}</p>
</template>

<script>
import DatePicker from "./components/DatePicker.vue";

export default {
  name: "App",
  components: {
    DatePicker,
  },
  data() {
    return {
      date: new Date(2020, 1, 1),
    };
  },
};
</script>

components/DatePicker.vue

<template>
  <div id="date-picker">
    <div>
      <label>year</label>
      <br />
      <select v-model="year">
        <option v-for="y in years" :key="y">
          {{ y }}
        </option>
      </select>
    </div>
    <div>
      <label>month</label>
      <br />
      <select v-model="month">
        <option v-for="m in 12" :key="m" :value="m - 1">
          {{ m }}
        </option>
      </select>
    </div>
    <div>
      <label>day</label>
      <br />
      <select v-model="day">
        <option v-for="d in maxDate" :key="d">
          {{ d }}
        </option>
      </select>
    </div>
  </div>
</template>

<style scoped>
#date-picker {
  display: flex;
}

#date-picker div {
  margin-right: 10px;
}
</style>

<script>
import moment from "moment";

export default {
  name: "DatePicker",
  props: {
    modelValue: Date,
  },
  data() {
    return {
      years: [],
      year: new Date().getFullYear(),
      month: 0,
      day: 1,
    };
  },
  methods: {
    emitDate() {
      const { year, month, day } = this;
      this.$emit("update:modelValue", new Date(year, month, day).toString());
    },
  },
  watch: {
    year() {
      this.emitDate();
    },
    month() {
      this.emitDate();
    },
    day() {
      this.emitDate();
    },
  },
  computed: {
    maxDate() {
      const { month } = this;
      if ([0, 2, 4, 6, 7, 9, 11].includes(month)) {
        return 31;
      } else if ([3, 5, 8, 10].includes(month)) {
        return 30;
      }
      return 28;
    },
  },
  beforeMount() {
    const currentYear = new Date().getFullYear();
    for (let i = -100; i <= 100; i++) {
      this.years.push(currentYear + i);
    }
    const d = moment(this.modelValue);
    this.year = +d.format("YYYY");
    this.month = +d.format("MM") - 1;
    this.day = +d.format("DD");
  },
};
</script>

In App.vue , we add the DatePicker component and bind it to a date string with v-model .

We create the date string with the Date constructor.

It’ll be converted to a string automatically when we get it from the modelValue prop.

Below that, we show the date value.

Then in DatePicker.vue , we add the 3 select elements to let us pick the year, month, and day.

We bind the select element value to reactive properties with v-model .

The value for the month starts with 0 and ends with 11 to match what the Date constructor accepts.

We use v-for to render the numbers for the value for the options.

Next, we add some styles to the style tag to make the dropdowns display side by side and add margins between them.

Then we have the component object.

The component takes the modelValue prop which is a string.

data returns the reactive properties we use for the template.

years is an array of years for the year dropdown which we’ll populate later.

year , month , and day are set to default values.

Next, we have the emitDate method to emit the update:modelValue event with the date string.

We call it in the year , month , and day watchers so it’ll run when any of these values change.

Then we add the maxDate computed property to return the max day we can set according to which month is chosen.

Since JavaScript Date constructor takes months that are 0 based, we check month values from 0 to 11, where 0 is January and 11 is December.

Finally, in the beforeMount hook, we populate the years array with 100 years before and after the current year.

And we get the modelValue prop’s value and parse the year, month, and day values

We do the parsing with the format method that comes with moment objects.

Now when we change the options in the drop-down, we should see the choices reflect in the text below.

Conclusion

We can create a drop-down component easily with Vue 3.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *