Skip to content

Commit

Permalink
fix(pat validation): With depending date validation also validate the…
Browse files Browse the repository at this point in the history
… dependend date.

Fixes: #970
  • Loading branch information
thet committed Mar 14, 2022
1 parent da0f97f commit ccbec3a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 30 deletions.
31 changes: 19 additions & 12 deletions src/pat/validation/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default Base.extend({
for (const [cnt, input] of this.inputs.entries()) {
// Cancelable debouncer.
const debouncer = utils.debounce((e) => {
this.check_input(input, e);
this.check_input({ input: input, event: e });
}, this.options.delay);

events.add_event_listener(
Expand All @@ -82,12 +82,12 @@ export default Base.extend({
this.el,
"submit",
`pat-validation--blur-${input.name}--${cnt}--validator`,
(e) => this.check_input(input, e) // immediate check with submit. Otherwise submit is not cancelable.
(e) => this.check_input({ input: input, event: e }) // immediate check with submit. Otherwise submit is not cancelable.
);
}
},

check_input(input, e) {
check_input({ input, event, stop = false }) {
if (input.disabled) {
// No need to check disabled inputs.
return;
Expand All @@ -97,7 +97,7 @@ export default Base.extend({
this.set_validity({ input: input, msg: "" });
const validity_state = input.validity;

if (e.submitter?.hasAttribute("formnovalidate")) {
if (event?.submitter?.hasAttribute("formnovalidate")) {
// Do not submit when a button with ``formnovalidate`` was used.
return;
}
Expand Down Expand Up @@ -139,6 +139,8 @@ export default Base.extend({

let not_after;
let not_before;
let not_after_el;
let not_before_el;
const date = new Date(input.value);
if (isNaN(date)) {
// Should not happen or input only partially typed in.
Expand All @@ -149,9 +151,8 @@ export default Base.extend({
not_after = new Date(input_options.not.after);
if (isNaN(not_after)) {
// Handle value as selector
not_after = document.querySelector(
input_options.not.after
)?.value;
not_after_el = document.querySelector(input_options.not.after);
not_after = not_after_el?.value;
not_after =
not_after &&
new Date(
Expand All @@ -167,9 +168,8 @@ export default Base.extend({
not_before = new Date(input_options.not.before);
if (isNaN(not_before)) {
// Handle value as selector
not_before = document.querySelector(
input_options.not.before
)?.value;
not_before_el = document.querySelector(input_options.not.before);
not_before = not_before_el?.value;
not_before =
not_before &&
new Date(
Expand All @@ -185,6 +185,13 @@ export default Base.extend({
} else if (not_before && date < not_before) {
this.set_validity({ input: input, msg: msg });
}
// always check the other input to clear/set errors
!stop && // do not re-check when stop is set to avoid infinite loops
not_after_el &&
this.check_input({ input: not_after_el, stop: true });
!stop &&
not_before_el &&
this.check_input({ input: not_before_el, stop: true });
}

if (!validity_state.customError) {
Expand Down Expand Up @@ -248,9 +255,9 @@ export default Base.extend({
}
}

if (e.type === "submit") {
if (event?.type === "submit") {
// Do not submit in error case.
e.preventDefault();
event.preventDefault();
}
this.set_error_message(input, input_options);
},
Expand Down
42 changes: 24 additions & 18 deletions src/pat/validation/validation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -824,15 +824,6 @@ describe("pat-validation", function () {
inp_end.value = "2020-10-05";
inp_end.dispatchEvent(events.change_event());
await utils.timeout(1); // wait a tick for async to settle.
expect(el.querySelectorAll("em.warning").length).toBe(1);
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
"The end date must on or before the start date."
);

// Violate the before/after constraint
inp_start.value = "2020-10-06";
inp_start.dispatchEvent(events.change_event());
await utils.timeout(1); // wait a tick for async to settle.
expect(el.querySelectorAll("em.warning").length).toBe(2);
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
"The start date must on or before the end date."
Expand All @@ -849,6 +840,18 @@ describe("pat-validation", function () {
await utils.timeout(1); // wait a tick for async to settle.
expect(el.querySelectorAll("em.warning").length).toBe(0);

// Violate the before/after constraint
inp_start.value = "2020-10-11";
inp_start.dispatchEvent(events.change_event());
await utils.timeout(1); // wait a tick for async to settle.
expect(el.querySelectorAll("em.warning").length).toBe(2);
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
"The start date must on or before the end date."
);
expect(el.querySelectorAll("em.warning")[1].textContent).toBe(
"The end date must on or before the start date."
);

// Fulfill the before/after constraint - start before end
inp_start.value = "2020-10-01";
inp_start.dispatchEvent(events.change_event());
Expand Down Expand Up @@ -947,15 +950,6 @@ describe("pat-validation", function () {
inp_end.value = "2022-01-05T09:00";
inp_end.dispatchEvent(events.change_event());
await utils.timeout(1); // wait a tick for async to settle.
expect(el.querySelectorAll("em.warning").length).toBe(1);
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
"The end date/time must on or before the start date/time."
);

// Violate the before/after constraint
inp_start.value = "2022-01-05T11:00";
inp_start.dispatchEvent(events.change_event());
await utils.timeout(1); // wait a tick for async to settle.
expect(el.querySelectorAll("em.warning").length).toBe(2);
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
"The start date/time must on or before the end date/time."
Expand All @@ -972,6 +966,18 @@ describe("pat-validation", function () {
await utils.timeout(1); // wait a tick for async to settle.
expect(el.querySelectorAll("em.warning").length).toBe(0);

// Violate the before/after constraint
inp_start.value = "2022-01-05T11:00";
inp_start.dispatchEvent(events.change_event());
await utils.timeout(1); // wait a tick for async to settle.
expect(el.querySelectorAll("em.warning").length).toBe(2);
expect(el.querySelectorAll("em.warning")[0].textContent).toBe(
"The start date/time must on or before the end date/time."
);
expect(el.querySelectorAll("em.warning")[1].textContent).toBe(
"The end date/time must on or before the start date/time."
);

// Fulfill the before/after constraint - start before end
inp_start.value = "2022-01-04T10:00";
inp_start.dispatchEvent(events.change_event());
Expand Down

0 comments on commit ccbec3a

Please sign in to comment.