はじめに
ユーザー登録を行うとき、生年月日を入力してもらうためにセレクトボックスを
用いるとします。ここで、生年月日のセレクトボックスの中身にHTMLやhamlで
直接データを入れ込んでしまうと4/31や2/31などが選択できてしまいます。
なので、年と月の情報をもとに日のセレクトボックスの中身を動的に変化させてみます。
実装にはJavascriptを用います。
(JQueryが入っているのでJavascriptのみの場合と記述方式が異なります)
環境
Rails 5.2.2.1
Ruby 2.5.1
jquery-rails 4.3.5
haml-rails 2.0.1
完成したもの
app/views/入力フォームが書いてあるファイル
= f.select :birth_year,["--"], {},{class: "セレクトボックスを修飾するクラスを入れる", id:"select_birth_year"}
%label
年
= f.select :birth_month, ["--"], {},{class: "セレクトボックスを修飾するクラスを入れる", id:"select_birth_month"}
%label
月
= f.select :birth_day, ["--"], {},{class: "セレクトボックスを修飾するクラスを入れる", id:"select_birth_day"}
%label
日
app/assets/javascripts/registration.js
$(document).on('turbolinks:load', function () {
// ユーザーの誕生日の閏年を動的に変化させる
// 誕生日の配列を宣言
var birth_year = [];
var birth_month = [];
var months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// 現在の年を取得する
var date = new Date();
var this_year = date.getFullYear();
var oldest_year = 1900;
// 誕生年月の配列を自動生成
for (var i = this_year; i >= oldest_year; i--) {
var year = { var: i, txt: String(i) };
birth_year.push(year);
}
for (var i = 1; i <= 12; i++) {
var month = { var: i, txt: String(i) };
birth_month.push(month);
}
// hamlの年と月のセレクトボックスに配列内容を反映させる
for (var i = 0; i < birth_year.length; i++) {
$("<option>", {
value: birth_year[i].var,
text: birth_year[i].txt
}).appendTo('#select_birth_year');
}
for (var i = 0; i < birth_month.length; i++) {
$("<option>", {
value: birth_month[i].var,
text: birth_month[i].txt
}).appendTo('#select_birth_month');
}
// 年、もしくは月のセレクトボックスの中身に変更があったら日の内容を変更する
$('#select_birth_year, #select_birth_month').change(function () {
// 日が入っているセレクトボックスの中身を空っぽにする
$('#select_birth_day').empty();
// 日が入るセレクトボックスにデフォルト値の'--'を入れる
$("<option>", {
text: '--'
}).appendTo('#select_birth_day');
// 2月の日にち、すなわちmonths[1]を28にセットし直す
months[1] = 28;
// 年と月に入力されている情報を取得する
var year = $('#select_birth_year').val();
var month = $("#select_birth_month").val();
// yearとmonth共に数字が入力されている、すなわち共に'--'でないときに実行
if (year != '--' && month != '--') {
// monthに2月が選択されている時実行
if (month == 2) {
// yearが閏年の時、2月の日付が格納されているmonths[1]の値を29にする
if (year % 4 == 0 && year % 100 == 0 && year % 400 == 0) {
months[1] = 29;
}
}
// 日を入れる配列を宣言し、閏年を考慮したデータを格納してhamlの日の
// セレクトボックスに反映させる
var birth_day = []
for (var i = 1; i <= months[month - 1]; i++) {
var day = { var: i, txt: String(i) };
birth_day.push(day);
}
for (var i = 0; i < birth_day.length; i++) {
$("<option>", {
value: birth_day[i].var,
text: birth_day[i].txt
}).appendTo('#select_birth_day');
};
};
});
});