Why is MoveToFirstError Called Before LinkedFormWithErrorID is Set in Form Validation Logic?
I’m working on a JavaScript form validation system that handles both a main form and linked forms (e.g., forms in modals). The issue is that MoveToFirstError is called before LinkedFormWithErrorID is set, causing the modal containing the linked form with errors to remain hidden. Additionally, the console logs show an unexpected sequence, indicating a timing issue in my validation logic.
Code Description
My validateForm function validates a main form and any linked forms specified via a LinkedForms attribute. If errors are found in a linked form, I set a global LinkedFormWithErrorID to the ID of the errored form and return early. After validation, if FormErrors > 0, I call MoveToFirstError to focus on the first error, which should also show the modal if the error is in a linked form.
However, the console logs show:
1-false
2-Setting LinkedFormWithErrorID to LayoutSelectModal
3-Form has 3 errors, not submitting.
This suggests MoveToFirstError runs before LinkedFormWithErrorID is set, so the modal doesn’t appear. The main form has no errors; all errors are in the linked form (LayoutSelectModal).
Problem Description
In my case:
The main form is error-free (FormErrors remains 0 after its validation).
The first linked form, LayoutSelectModal, has three errors, causing FormErrors to become 3.
When errors are found in a linked form, I set the global LinkedFormWithErrorID to the ID of the errored form (e.g., “LayoutSelectModal”) and return early to stop further validation.
After validation, if FormErrors > 0, I call MoveToFirstError to focus on the first error, which should also unhide the modal if the error is in a linked form.
Expected Behavior
1-Complete all validation (main and linked forms) first (return early as soon as an error is encountered with any form skipping further unnecessary validation ).
2-Set LinkedFormWithErrorID if a linked form has errors.
3-Call MoveToFirstError once, after validation, to focus on the first error and show the modal if needed.
4-Console logs should show Setting LinkedFormWithErrorID to LayoutSelectModal before false from MoveToFirstError.
Relevant Code
validateForm Function
This validates the main form and linked forms, setting FormErrors and LinkedFormWithErrorID.
let FormErrors = 0; // Global error counter
let LinkedFormWithErrorID = false; // Tracks ID of errored linked form
function validateForm(Form) {
FormErrors = 0;
let InputGroups = Form.getElementsByClassName("InputGroup");
// ... (input group validation logic omitted for brevity) ...
// Linked Forms Validation
LinkedFormWithErrorID = false; // Reset
if (Form.hasAttribute("LinkedForms")) {
const linkedFormIds = Form.getAttribute("LinkedForms").split(",").map((id) => id.trim());
for (const linkedFormId of linkedFormIds) {
const linkedForm = document.getElementById(linkedFormId);
if (linkedForm) {
const isValid = validateForm(linkedForm); // Recursive call
if (!isValid) {
LinkedFormWithErrorID = linkedFormId;
console.log("Setting LinkedFormWithErrorID to " + LinkedFormWithErrorID);
return false; // Early return on error
}
} else {
console.warn(`Linked form with ID "${linkedFormId}" not found.`);
}
}
}
// Check for errors
if (FormErrors > 0) {
MoveToFirstError(Form); // Focus on first error
return false;
} else {
return true;
}
}
MoveToFirstError Function
This focuses on the first error in the main form or linked form and should show the modal if needed.
function MoveToFirstError(form) {
console.log(LinkedFormWithErrorID); // Logs 'false' first
const firstError = form.getElementsByClassName('Error')[0];
if (firstError) {
firstError.focus();
firstError.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
if (form.hasAttribute('MultiPage')) {
ShowFirstErrorFormStep(form, firstError);
}
return false;
}
if (LinkedFormWithErrorID) {
const linkedForm = document.getElementById(LinkedFormWithErrorID);
if (linkedForm) {
if (linkedForm.parentNode.parentNode.classList.contains('modal')) {
linkedForm.parentNode.parentNode.classList.remove('hidden'); // Show modal
}
linkedForm.classList.remove('hidden');
const firstError = linkedForm.getElementsByClassName('Error')[0];
if (firstError) {
firstError.focus();
firstError.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
return false;
}
}
return true;
}
SubmitForm Function
This triggers validation and submission.
async function SubmitForm(Form, ReqMethod, ReqTarget, formData) {
if (Form) {
validateForm(Form);
if (FormErrors > 0) {
console.warn("Form has " + FormErrors + " errors, not submitting.");
return {
success: false,
message: "Form has " + FormErrors + " errors, not submitting.",
};
}
// ... (data collection and submission logic omitted) ...
}
// ... (fetch logic omitted) ...
}
Questions
Why is MoveToFirstError called before LinkedFormWithErrorID is set?
How can I ensure all validation completes before focusing on the first error?
What changes are needed to make the modal appear when errors are in a linked form?
Any help or insights would be greatly appreciated!