[JavaScript]プルダウンで生年月日を入力するフォーム


はじめまして。Leeと申します。
プログラミングの学習を始めて約半年の私が詰まったところなどをまとめていきます。

今回が初投稿になります。第一弾は下図のような、JavaScriptで生年月日を年/月/日と分けてプルダウンで選択するフォームを作成します。

例えば2月30日など存在しない日付などは選べないようにします。
なので日の選択肢は、年月によって動的に変化することを狙います。

html

index.html
<div>
  <select id="select_year" name="year"></select><select id="select_month" name="month"></select><select id="select_day" name="day"></select></div>

フォームの中にこれを設置します。年月日それぞれのタブがあって、それぞれに選択肢を<option>をJavaScriptで生成します。
JavaScriptで指定しやすいようにするためにidを付与しておきます。
name属性はフォームで送られる情報の名前になります。

JavaScript

main.js
(function(){
  'use strict';

   const select_year = document.getElementById('select_year');
   const select_month = document.getElementById('select_month');
   const select_day = document.getElementById('select_day');
   let i;

  function $set_year(){
    // 年を生成(100年分)
    for(i = 1919; i < 2020; i++){
      let op = document.createElement('option');
      op.value = i;
      op.text = i;
      select_year.appendChild(op);
    }
  function $set_month(){
    // 月を生成(12)
    for(i = 1; i <= 12; i++){
      let op = document.createElement('option');
      op.value = i;
      op.text = i;
      select_month.appendChild(op);
    }
  }

  function $set_day(){
    //日の選択肢を空にする
    let children = select_day.children
    while(children.length){
      children[0].remove()
    }
    // 日を生成(動的に変える)
    if(select_year.value !== '' &&  select_month.value !== ''){
      const last_day = new Date(select_year.value,select_month.value,0).getDate()

      for (i = 1; i <= last_day; i++) {
        let op = document.createElement('option');
        op.value = i;
        op.text = i;
        select_day.appendChild(op);
      }
    }
  }

  // load時、年月変更時に実行する
  window.onload = function(){
    $set_year();
    $set_month();
    $set_day();
    select_year.addEventListener('change',$set_day)
    select_month.addEventListener('change',$set_day)
  }
})();

JavaScriptは即時関数でHTMLの読み込みが終わってから実行します。

簡単に解説すると、$set_yaer$set_monthはfor構文で<option>を生成して、それぞれの<select>の子要素として配置しています。

一度作ってしまえばいいので、直接HTMLに<option>を配置してもいいかもしれません。

日に関しては、まず選択肢を全て空にします。日は28日以上31日以下なのでそれだけを変化させてもいいですが、処理が面倒そうだったので、全部消して再配置する方法をとりました。

年月が未選択の時以外に年月から最終日を取得しています。
最終日が分かれば、あとは年月と同様に<option>を最終日分生成します。

最後に画面の更新時に年月をセットし、年月が選択された時に日の選択肢を配置しています。
ただもし、年月を選びなおした時に日を再配置するため、addEventListenerのchangeを使っています。

まとめ

年月からその月の最終日を取得して<option>を生成する処理でした。
実際にはバリデーションでリダイレクトされた時に元の値を復元することの方がなかなか理解できず苦労しました。

初めて書いたので、おかしい点やもっとこうした方がいいなどのアドバイスなどあれば、よろしくお願いします。

参考リンク