|
54 | 54 | id="@Model.DayId"
|
55 | 55 | name="@Model.DayId"
|
56 | 56 | value="@Model.DayValue"
|
57 |
| - type="number" |
| 57 | + type="text" |
58 | 58 | pattern="[0-9]*"
|
59 | 59 | min="1"
|
60 | 60 | max="31"
|
61 | 61 | step="1"
|
62 |
| - inputmode="numeric" /> |
| 62 | + inputmode="numeric" |
| 63 | + aria-describedby="date-error" aria-invalid="false" /> |
63 | 64 | </div>
|
64 | 65 | </div>
|
65 | 66 | <div class="nhsuk-date-input__item">
|
|
69 | 70 | id="@Model.MonthId"
|
70 | 71 | name="@Model.MonthId"
|
71 | 72 | value="@Model.MonthValue"
|
72 |
| - type="number" |
| 73 | + type="text" |
73 | 74 | pattern="[0-9]*"
|
74 | 75 | min="1"
|
75 | 76 | max="12"
|
76 | 77 | step="1"
|
77 |
| - inputmode="numeric" /> |
| 78 | + inputmode="numeric" |
| 79 | + aria-describedby="date-error" aria-invalid="false" /> |
78 | 80 | </div>
|
79 | 81 | </div>
|
80 | 82 | <div class="nhsuk-date-input__item">
|
|
84 | 86 | id="@Model.YearId"
|
85 | 87 | name="@Model.YearId"
|
86 | 88 | value="@Model.YearValue"
|
87 |
| - type="number" |
| 89 | + type="text" |
88 | 90 | pattern="[0-9]*"
|
89 | 91 | min="1900"
|
90 | 92 | max="9999"
|
91 | 93 | step="1"
|
92 |
| - inputmode="numeric" /> |
| 94 | + inputmode="numeric" |
| 95 | + aria-describedby="date-error" aria-invalid="false" /> |
93 | 96 | </div>
|
94 | 97 | </div>
|
| 98 | + <span id="date-error" class="error-message--margin-bottom-1 nhsuk-error-message" aria-live="polite" style="visibility: hidden;"> |
| 99 | + </span> |
95 | 100 | </div>
|
96 | 101 | </fieldset>
|
| 102 | + <script> |
| 103 | + const fields = [@Model.DayId, @Model.MonthId, @Model.YearId]; |
| 104 | +
|
| 105 | + const errorElement = document.getElementById('date-error'); |
| 106 | + for (let field of fields) { |
| 107 | + const inputElement = document.getElementById(field.id); |
| 108 | +
|
| 109 | + inputElement.addEventListener('input', function (event) { |
| 110 | +
|
| 111 | + if (event.inputType === 'deleteContentBackward') { |
| 112 | + return; |
| 113 | + } |
| 114 | +
|
| 115 | + const value = event.data; |
| 116 | + const min = parseInt(inputElement.getAttribute('min')); |
| 117 | + const max = parseInt(inputElement.getAttribute('max')); |
| 118 | +
|
| 119 | + inputElement.setAttribute('aria-invalid', 'false'); |
| 120 | + errorElement.textContent = ''; |
| 121 | + errorElement.style.visibility = 'hidden'; |
| 122 | +
|
| 123 | + setTimeout(function () { |
| 124 | + if (value < 1 || value > max || !value.match(/^[0-9]*$/)) { |
| 125 | + inputElement.value = inputElement.value.slice(0, -1) + 1; |
| 126 | + inputElement.value = inputElement.value.slice(0, -1); |
| 127 | + inputElement.setAttribute('aria-invalid', 'true'); |
| 128 | + errorElement.textContent = `Invalid input. Please enter a number between ${min} and ${max}.`; |
| 129 | + errorElement.style.visibility = 'visible'; |
| 130 | + } |
| 131 | + }, 0); |
| 132 | + }); |
| 133 | + } |
| 134 | + </script> |
97 | 135 | </div>
|
0 commit comments