Skip to content

Commit 831ee60

Browse files
committed
fix(pat-validation): Fallback error messages for not-before and not-after.
If no error messages were provided for the not-before and not-after constraints on date fields no error messages were shown even when those inputs had form validation errors. Now we are always providing a fallback error message based on the label or input name.
1 parent c8c656a commit 831ee60

File tree

2 files changed

+179
-3
lines changed

2 files changed

+179
-3
lines changed

src/pat/validation/validation.js

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ export default Base.extend({
157157
});
158158
} else if (input_options.not.after || input_options.not.before) {
159159
const msg = input_options.message.date || input_options.message.datetime;
160+
const msg_default_not_before = "The date must be after %{attribute}";
161+
const msg_default_not_after = "The date must be before %{attribute}";
160162

161163
let not_after;
162164
let not_after_el;
@@ -201,9 +203,47 @@ export default Base.extend({
201203
const date = new Date(input.value);
202204

203205
if (not_after && date > not_after) {
204-
this.set_validity({ input: input, msg: msg });
206+
let msg_attr;
207+
// Try to construct a meaningfull error message
208+
if (!not_after_el && input_options.not.after) {
209+
// fixed date case
210+
msg_attr = input_options.not.after;
211+
} else {
212+
// Get the label + other text content within the
213+
// label and replace all whitespace and newlines
214+
// with a single space.
215+
msg_attr = not_after_el?.labels?.[0]?.textContent.replace(
216+
/\s\s+/g, // replace all whitespace
217+
" " // with a single space
218+
);
219+
msg_attr = msg_attr || not_after_el.name;
220+
}
221+
this.set_validity({
222+
input: input,
223+
msg: msg || msg_default_not_after,
224+
attribute: msg_attr.trim(),
225+
});
205226
} else if (not_before && date < not_before) {
206-
this.set_validity({ input: input, msg: msg });
227+
let msg_attr;
228+
// Try to construct a meaningfull error message
229+
if (!not_before_el && input_options.not.before) {
230+
// fixed date case
231+
msg_attr = input_options.not.before;
232+
} else {
233+
// Get the label + other text content within the
234+
// label and replace all whitespace and newlines
235+
// with a single space.
236+
msg_attr = not_before_el?.labels?.[0]?.textContent.replace(
237+
/\s\s+/g, // replace all whitespace
238+
" " // with a single space
239+
);
240+
msg_attr = msg_attr || not_before_el.name;
241+
}
242+
this.set_validity({
243+
input: input,
244+
msg: msg || msg_default_not_before,
245+
attribute: msg_attr.trim(),
246+
});
207247
}
208248
}
209249

src/pat/validation/validation.test.js

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -945,7 +945,7 @@ describe("pat-validation", function () {
945945
expect(el.querySelectorAll("em.warning").length).toBe(0);
946946
});
947947

948-
it("5.4 - validates dates with before/after as pattern config attributes with custom error message.", async function () {
948+
it("5.4.1 - validates dates with before/after as pattern config attributes with custom error message.", async function () {
949949
document.body.innerHTML = `
950950
<form class="pat-validation">
951951
<input
@@ -987,6 +987,142 @@ describe("pat-validation", function () {
987987
expect(el.querySelectorAll("em.warning").length).toBe(0);
988988
});
989989

990+
it("5.4.2 - validates dates with before/after as pattern config attributes with NO custom error message, using fixed dates.", async function () {
991+
document.body.innerHTML = `
992+
<form class="pat-validation">
993+
<input
994+
type="date"
995+
name="date"
996+
data-pat-validation="
997+
not-before: 2011-11-11;
998+
not-after: 2022-02-22;
999+
" />
1000+
</form>
1001+
`;
1002+
1003+
const el = document.querySelector(".pat-validation");
1004+
const inp = el.querySelector("[name=date]");
1005+
1006+
new Pattern(el);
1007+
await utils.timeout(1); // wait a tick for async to settle.
1008+
1009+
// No error when left empty and not required.
1010+
inp.value = "";
1011+
inp.dispatchEvent(events.change_event());
1012+
await utils.timeout(1); // wait a tick for async to settle.
1013+
expect(el.querySelectorAll("em.warning").length).toBe(0);
1014+
1015+
inp.value = "2010-10-10";
1016+
inp.dispatchEvent(events.change_event());
1017+
await utils.timeout(1); // wait a tick for async to settle.
1018+
expect(el.querySelectorAll("em.warning").length).toBe(1);
1019+
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
1020+
"The date must be after 2011-11-11"
1021+
);
1022+
1023+
inp.value = "2023-02-23";
1024+
inp.dispatchEvent(events.change_event());
1025+
await utils.timeout(1); // wait a tick for async to settle.
1026+
expect(el.querySelectorAll("em.warning").length).toBe(1);
1027+
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
1028+
"The date must be before 2022-02-22"
1029+
);
1030+
1031+
inp.value = "2022-01-01";
1032+
inp.dispatchEvent(events.change_event());
1033+
await utils.timeout(1); // wait a tick for async to settle.
1034+
1035+
expect(el.querySelectorAll("em.warning").length).toBe(0);
1036+
});
1037+
1038+
it("5.4.3 - validates dates with before/after as pattern config attributes with NO custom error message, using labels.", async function () {
1039+
document.body.innerHTML = `
1040+
<form class="pat-validation">
1041+
<label>ye date
1042+
<input
1043+
type="date"
1044+
name="date1"
1045+
data-pat-validation="
1046+
not-after: [name=date2];
1047+
" />
1048+
</label>
1049+
<label>woo date
1050+
<input
1051+
type="date"
1052+
name="date2"
1053+
data-pat-validation="
1054+
not-before: [name=date1];
1055+
" />
1056+
</label>
1057+
</form>
1058+
`;
1059+
1060+
const el = document.querySelector(".pat-validation");
1061+
const inp1 = el.querySelector("[name=date1]");
1062+
const inp2 = el.querySelector("[name=date2]");
1063+
1064+
new Pattern(el);
1065+
await utils.timeout(1); // wait a tick for async to settle.
1066+
1067+
inp1.value = "2010-10-10";
1068+
inp2.value = "2001-01-01";
1069+
1070+
inp1.dispatchEvent(events.change_event());
1071+
await utils.timeout(1); // wait a tick for async to settle.
1072+
expect(el.querySelectorAll("em.warning").length).toBe(2);
1073+
1074+
console.log(document.body.innerHTML);
1075+
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
1076+
"The date must be before woo date"
1077+
);
1078+
1079+
expect(el.querySelectorAll("em.warning")[1].textContent).toBe(
1080+
"The date must be after ye date"
1081+
);
1082+
});
1083+
1084+
it("5.4.4 - validates dates with before/after as pattern config attributes with NO custom error message, using input names.", async function () {
1085+
document.body.innerHTML = `
1086+
<form class="pat-validation">
1087+
<input
1088+
type="date"
1089+
name="date1"
1090+
data-pat-validation="
1091+
not-after: [name=date2];
1092+
" />
1093+
<input
1094+
type="date"
1095+
name="date2"
1096+
data-pat-validation="
1097+
not-before: [name=date1];
1098+
" />
1099+
</form>
1100+
`;
1101+
1102+
const el = document.querySelector(".pat-validation");
1103+
const inp1 = el.querySelector("[name=date1]");
1104+
const inp2 = el.querySelector("[name=date2]");
1105+
1106+
new Pattern(el);
1107+
await utils.timeout(1); // wait a tick for async to settle.
1108+
1109+
inp1.value = "2010-10-10";
1110+
inp2.value = "2001-01-01";
1111+
1112+
inp1.dispatchEvent(events.change_event());
1113+
await utils.timeout(1); // wait a tick for async to settle.
1114+
expect(el.querySelectorAll("em.warning").length).toBe(2);
1115+
1116+
console.log(document.body.innerHTML);
1117+
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
1118+
"The date must be before date2"
1119+
);
1120+
1121+
expect(el.querySelectorAll("em.warning")[1].textContent).toBe(
1122+
"The date must be after date1"
1123+
);
1124+
});
1125+
9901126
it("5.5 - validates dates with before/after constraints", async function () {
9911127
document.body.innerHTML = `
9921128
<form class="pat-validation">

0 commit comments

Comments
 (0)