LoginSignup
5
3

More than 3 years have passed since last update.

生年月日入力フォーム~Vuetifyのselect formを使った実装例~

Posted at

環境 Vue 2.6.11 Vuetify 2.4.0

実装した時の備忘録なのでメモが粗いです。。
もっといい書き方があればコメントいただければ嬉しいです!

やりたいこと

Vuetifyselect form を使って生年月日の入力フォームを作りたい
イメージ1
年もしくは月が変わったら、選択されている日をクリアして選択し直すようにする
イメージ2

package.json
package.json
{
  "name": "sample-app",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "vuetify": "^2.4.0",
    "vuex": "^3.4.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/eslint-config-prettier": "^6.0.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-vue": "^6.2.2",
    "prettier": "^2.2.1",
    "sass": "^1.32.0",
    "sass-loader": "^10.0.0",
    "vue-cli-plugin-vuetify": "~2.3.1",
    "vue-template-compiler": "^2.6.11",
    "vuetify-loader": "^1.7.0"
  }
}

実装

Form.vue
<template>
  <v-card width="480">
    <v-card-text>
      <div class="mb-4">- 生年月日 -</div>
      <v-row>
        <v-col cols="6">
          <v-select label="西暦" :items="years" v-model="year" @change="resetDay" filled dense></v-select>
        </v-col>
        <v-col cols="3">
          <v-select label="月" :items="months" v-model="month" @change="resetDay" filled dense></v-select>
        </v-col>
        <v-col cols="3">
          <v-select label="日" :items="days" v-model="day" filled dense></v-select>
        </v-col>
      </v-row>
      <div class="text-center">
        <v-btn class="ma-2" color="teal" dark>次へ</v-btn>
      </div>
    </v-card-text>
    <pre>{{ $data }}</pre>
  </v-card>
</template>

<script>
export default {
  data: () => ({
    year: '',
    month: '',
    day: '',
  }),
  methods: {
    resetDay() {
      this.day = ''
    },
  },
  computed: {
    years() {
      const years = []
      for (let year = 1900; year <= new Date().getFullYear(); year++) {
        years.push(year)
      }
      return years
    },
    months() {
      const months = [...Array(12)].map((ele, i) => i + 1)
      return months
    },
    days() {
      let days = []
      if ((this.month === 2 && this.year % 4 === 0 && this.year % 100 !== 0) || (this.month === 2 && this.year % 400 === 0)) {
        days = [...Array(29)].map((ele, i) => i + 1)
      } else if (this.month === 2) {
        days = [...Array(28)].map((ele, i) => i + 1)
      } else if (this.month === 4 || this.month === 6 || this.month === 9 || this.month === 11) {
        days = [...Array(30)].map((ele, i) => i + 1)
      } else {
        days = [...Array(31)].map((ele, i) => i + 1)
      }
      return days
    },
  },
}
</script>

メモ

  • 入力フォームはVuetifyのSelectsコンポーネントを使用
  • 年はyears、月はmonths、日はdaysとしてcomputedプロパティで管理
  • 年は、1900年〜今年(new Date().getFullYear())までが表示するようにしている
  • 月は、1〜12の整数を配列に入れる方法を[...Array(12)].map((ele, i) => i + 1)で実装 ※参考記事 ワンライナーで0から10の値を持つ配列を作る方法
  • 年もしくは月が変わったら、v-onでchangeイベントを発火、@change="resetDay"と記述してresetDayメソッドを定義、入力している日をクリアする
  • うるう年の換算は以下で実装
let days = []
if ((this.month === 2 && this.year % 4 === 0 && this.year % 100 !== 0) || (this.month === 2 && this.year % 400 === 0)) {
  days = [...Array(29)].map((ele, i) => i + 1)
} else if (this.month === 2) {
  days = [...Array(28)].map((ele, i) => i + 1)
} else if (this.month === 4 || this.month === 6 || this.month === 9 || this.month === 11) {
  days = [...Array(30)].map((ele, i) => i + 1)
} else {
  days = [...Array(31)].map((ele, i) => i + 1)
}
5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3