Contact Form Custom Validation Messages

Hello, I would like to add custom validation messages to Contact form. For example instead of default “Please fill out this field”, I want to put “Please enter first name”, “Please enter last name”, “Email address is invalid”.

I added js on event “on(‘submit’, function(event)” to validate the fields and use my validation messages and it works.

However, the problem seems that with the new Shopify hCaptcha it still submits the form instantaneously upon submit. Meaning, the on(‘submit’) gets triggered and my custom validation messages appear, but the form is submitted immediately; it doesn’t stay on the page to show the validation messages.

We don’t want to disable hCaptcha. I tried adding " event.preventDefault()" but it still calls hCaptcha and the page forwards upon clicking Submit. It seems the hCaptcha code is overriding something that doesn’t allow “preventDefault()” from firing.

Any suggestions would be much appreciated.

Hi,

Updated JavaScript Solution

Code example

document.addEventListener('DOMContentLoaded', function () {
  const form = document.querySelector('form'); // Adjust selector if needed

  form.addEventListener('submit', function (event) {
    event.preventDefault(); // Prevent form submission

    // Your custom validation logic
    let isValid = true;
    const firstName = document.querySelector('[name="first_name"]'); // Adjust selector if needed
    const lastName = document.querySelector('[name="last_name"]'); // Adjust selector if needed
    const email = document.querySelector('[name="email"]'); // Adjust selector if needed

    if (!firstName.value) {
      isValid = false;
      showError('first_name', 'Please enter first name');
    }

    if (!lastName.value) {
      isValid = false;
      showError('last_name', 'Please enter last name');
    }

    if (!validateEmail(email.value)) {
      isValid = false;
      showError('email', 'Email address is invalid');
    }

    if (isValid) {
      // Trigger hCaptcha after custom validation
      if (typeof grecaptcha !== 'undefined') {
        grecaptcha.execute(); // Assuming you're using reCAPTCHA v3
      } else {
        form.submit(); // Fallback if hCaptcha is not found
      }
    }
  });

  function showError(fieldName, message) {
    // Your logic to display the error message
    // For example, update a specific element's text content
    document.querySelector(`#${fieldName}-error`).textContent = message;
  }

  function validateEmail(email) {
    // Simple email validation regex
    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return regex.test(email);
  }
});

Handle hCaptcha Callback

Code example

function onSubmit(e) {
  e.preventDefault();
  grecaptcha.execute();
}

function onCaptchaSuccess(token) {
  // Submit form after successful hCaptcha validation
  document.querySelector('form').submit();
}

function onCaptchaError() {
  // Handle hCaptcha error if needed
}

grecaptcha.ready(function () {
  document.querySelector('form').addEventListener('submit', onSubmit);
  grecaptcha.execute = function () {
    // Your hCaptcha execution logic
    // On success, call onCaptchaSuccess(token);
    // On error, call onCaptchaError();
  }
});

Did this get resolved? I have the same issue as the form goes through the validation but then hcaptcha submits it independently on the result. The code above is for grecaptcha which does not exist in the latest shopify, but hcaptcha exists.

Is there anything else we can do to avoid the submissions unless via javascript we say form.submit() ?

I figure out this way, it may help someone else

Once you get the form element set the action to nothing, i.e. ‘javascript:’ for example, and store the real action in an attribute.

document.addEventListener('DOMContentLoaded', function () {
   const form = document.querySelector('#yourformid');
   form.setAttribute('data-action', form.action) // Save the action
   form.action = 'javascript:;' 
}

When the submit event arrives, if form is validated call the submit with the saved attribute action.

form.addEventListener('submit', function (event) {
      event.preventDefault()  // Prevent form submission

... code to validate the fields...

if (isValid) {
 event.target.action = event.target.getAttribute('data-action')
 if (window.Shopify?.captcha?.protect) {
   window.Shopify.captcha.protect(form, () => {
      new FormData(event.target);
   });
  } else {
     new FormData(event.target);
} else {
   return false
}
}

If someone has a better approach let me know.