前回の続きです。
環境
- Visual Studio 2019 16.4.0 Preview 1.0
- .NET Core SDK 3.0.100
- Firefox US版 69.0.1(64bit)
Range範囲外の値でも入力できる
前回では触れませんでしたが、Rangeを指定してもその範囲外の値を指定できます。
(もちろん、検証時エラーになりますが)
これはあまりユーザーフレンドリーとは言えないので、そもそも入力できないようにフォームを制限する方法を考えます。
HTMLを確認する
Range属性付きのプロパティとして生成されるHTMLは下記の通り(前回のものなのでエラー時のもの)で、検証用のdata-val-range-max
やdata-val-range-max
がありますが、max
やmin
はありません。
<input class="text-box single-line input-validation-error" data-val="true" data-val-range="Value for DemoDate must be between 2019/09/09 and 2019/09/19" data-val-range-max="09/19/2019 00:00:00" data-val-range-min="09/09/2019 00:00:00" data-val-required="The DemoDate field is required." id="RangeDateDemo_DemoDate" name="RangeDateDemo.DemoDate" type="date" value="" aria-describedby="RangeDateDemo_DemoDate-error" aria-invalid="true">
当然max
やmin
を生やすことになるのですが、一つ注意点として、どうやらその日付書式は"YYYY-MM-dd"である必要があるということです。
これを考慮すると作成するコードは下記のようになります。
<!-- Pages/_Shared/ValidationScriptsPartial.cshtml --> <script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script> <script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script> @*前回はここから追加*@ <script> //original: https://stackoverflow.com/questions/52543413/datetime-client-side-validation-fails-due-to-formatting $.validator.methods.range = function (value, element, param) { if ($(element).attr('type') == 'date') { var min = $(element).attr('data-val-range-min'); var max = $(element).attr('data-val-range-max'); var date = new Date(value).getTime(); var minDate = new Date(min).getTime() || 0; var maxDate = new Date(max).getTime() || 8640000000000000; return this.optional(element) || (date >= minDate && date <= maxDate); } // use the default method return this.optional(element) || (value >= param[0] && value <= param[1]); }; @*今回はここから追加*@ (function () { function formatDate(date) { var d = new Date(date); var year = d.getFullYear(); var month = (d.getMonth() + 1).toString(); var day = d.getDate().toString(); if (month.length < 2) month = '0' + month; if (day.length < 2) day = '0' + day; return [year, month, day].join('-'); } function setMinMax(inputElem, f) { Object.keys(inputElem).forEach(function (key) { var elem = inputElem[key]; var rangeMin = elem.getAttribute("data-val-range-min"); var rangeMax = elem.getAttribute("data-val-range-max"); if (rangeMin) elem.setAttribute("min", f(rangeMin)); if (rangeMax) elem.setAttribute("max", f(rangeMax)); }); } var inputDateElements = document.querySelectorAll('input[type="date"]'); setMinMax(inputDateElements, formatDate); var inputNumberElements = document.querySelectorAll('input[type="number"]'); setMinMax(inputNumberElements, function (x) { return x; }); })() @*今回はここまで追加*@ </script> @*前回はここまで追加*@
これにより目的のmax
やmin
を生やします。最後のものは標準の整数に対応したものです。
<input class="text-box single-line" data-val="true" data-val-range="Value for DemoDate must be between 2019/09/09 and 2019/09/19" data-val-range-max="09/19/2019 00:00:00" data-val-range-min="09/09/2019 00:00:00" data-val-required="The DemoDate field is required." id="RangeDateDemo_DemoDate" name="RangeDateDemo.DemoDate" type="date" value="" min="2019-09-09" max="2019-09-19">
下図のように入力フォームがRangeの範囲で制限されています。
おまけ
MS Edge 18で確認したら、制限後はあまり見ない感じのUIとなっていました。