DEV Community

Explorer
Explorer

Posted on

Overriding Joget Form Submission for Multi-Field Validation & Smooth Scrolling

In long multi-section forms built with Joget DX, standard field validators display error messages next to each input. When a user submits a long form with multiple missing fields, they often have to scroll up and down repeatedly to find which required fields failed.

In this guide, we'll write a JavaScript snippet that intercepts Joget's submit button (#section-actions input), collects all unfulfilled field requirements, displays a clean SweetAlert popup summary, and smooth-scrolls directly to the first invalid field.


How It Works

  1. Event Interception: The script unbinds Joget's default click handler on section action buttons ($("#section-actions input").not("#cancel, #saveAsDraft").off("click")) and attaches a custom validator wrapper.
  2. Dynamic Inspection: It iterates through a validation matrix, automatically skipping fields that are currently disabled (disabled) or read-only (readonly).
  3. Modal Alert & Smooth Scroll: If validation fails, all missing field notifications are concatenated into a modal alert. Upon closing the alert, element.scrollIntoView({ behavior: "smooth", block: "center" }) automatically focuses the user's screen on the first invalid input.

The Code

Add a Custom HTML element at the bottom of your Joget form and paste the code below:

<!-- Include SweetAlert2 for clean modal notifications (Optional) -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>

<script>
$(document).ready(function () {
  // Allow Joget internal scripts to finish initializing
  setTimeout(function () {
    const $submitButtons = $("#section-actions input").not("#cancel, #saveAsDraft");

    // Remove default submit handler and attach custom validation suite
    $submitButtons.off("click").on("click", function (event) {
      event.preventDefault();
      const $clickedButton = $(this);

      // Define validation rules array
      const validationRules = [
        {
          element: "input[name=request_date]",
          value: $("input[name=request_date]").val()?.trim(),
          isDisabled: $("input[name=request_date]").prop("disabled") || $("input[name=request_date]").prop("readonly"),
          message: "• Please select the Request Date."
        },
        {
          element: "select[name=department_category]",
          value: $("select[name=department_category]").val()?.trim(),
          isDisabled: $("select[name=department_category]").prop("disabled"),
          message: "• Please select a Department Category."
        },
        {
          element: "textarea[name=justification]",
          value: $("textarea[name=justification]").val()?.trim(),
          isDisabled: $("textarea[name=justification]").prop("disabled"),
          message: "• Please provide a business Justification."
        }
      ];

      let firstInvalidSelector = null;
      const errorList = [];

      // Inspect enabled fields only
      validationRules.forEach(rule => {
        if (!rule.isDisabled) {
          const isValid = !!rule.value;
          if (!isValid) {
            errorList.push(rule.message);
            if (!firstInvalidSelector) {
              firstInvalidSelector = rule.element;
            }
          }
        }
      });

      // Display validation modal if errors are present
      if (errorList.length > 0) {
        if (typeof Swal !== "undefined") {
          Swal.fire({
            title: "Required Fields Missing",
            html: "<div style='text-align:left; font-size:14px; line-height:1.6;'>" + errorList.join("<br>") + "</div>",
            icon: "warning",
            confirmButtonColor: "#0056b3",
            confirmButtonText: "Review Form"
          }).then(() => {
            // Smooth-scroll screen to first invalid field
            setTimeout(() => {
              const targetElem = document.querySelector(firstInvalidSelector);
              if (targetElem) {
                targetElem.scrollIntoView({ behavior: "smooth", block: "center" });
                targetElem.focus();
              }
            }, 200);
          });
        } else {
          alert("Please complete the following required fields:\n\n" + errorList.join("\n"));
        }
        return false;
      }

      // All validations passed - submit form normally
      $clickedButton.closest("form").submit();
    });
  }, 800);
});
</script>
Enter fullscreen mode Exit fullscreen mode

Key Benefits

  • Better User Experience: Displays a single consolidated popup summary rather than multiple scattered error labels.
  • Auto Focus: Automatically scrolls the browser window to the first field needing attention.
  • Conditional Aware: Smartly ignores fields hidden or disabled by Joget Form Visibility rules.

Top comments (0)