JavaScript Prevent Form Submit Until Validation

JavaScript Prevent Form Submit Until Validation
Code Snippet:Form Validation: Validate on Submit
Author: Chris Ferdinandi
Published: January 12, 2024
Last Updated: January 22, 2024
Downloads: 712
License: MIT
Edit Code online: View on CodePen
Read More

This JavaScript code helps you to create a functionality to prevent form submit until validation is complete. It adds the "novalidate" attribute to the form, ensuring that HTML5 native validation is bypassed. The code then validates each form field on blur, displaying relevant error messages and styling.

On form submission, it checks all fields for errors, preventing submission if any are found and focusing on the first erroneous field. This ensures user-entered data meets specified criteria for name, email, URL, and radio buttons.

You can integrate this code to enhance your form’s user experience and data accuracy.

How to Create Functionality in JavaScript to Prevent Form Submit Until Validation

1. First, copy and paste the following HTML code into your web page. This code includes a simple form with fields for name, email, URL, and radio buttons. Ensure your form has the class "validate" for the JavaScript code to target.

  1. <form class="validate" action="#">
  2. <div>
  3. <label for="text">Name</label>
  4. <input type="text" id="text" required>
  5. </div>
  6.  
  7. <div>
  8. <label for="email">Email</label>
  9. <input type="email" id="email" title="The domain portion of the email address is invalid (the portion after the @)." pattern="^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*(\.\w{2,})+$" required>
  10. </div>
  11.  
  12. <div>
  13. <label for="url">URL</label>
  14. <input type="url" id="url" title="The URL is a missing a TLD (for example, .com)." pattern="^(?:(?:https?|HTTPS?|ftp|FTP):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-zA-Z\u00a1-\uffff0-9]-*)*[a-zA-Z\u00a1-\uffff0-9]+)(?:\.(?:[a-zA-Z\u00a1-\uffff0-9]-*)*[a-zA-Z\u00a1-\uffff0-9]+)*(?:\.(?:[a-zA-Z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$" required>
  15. </div>
  16.  
  17. <div>
  18. <strong>Radio Buttons</strong>
  19. <label class="label-normal">
  20. <input type="radio" name="radio" id="radio-1" required>
  21. Yes
  22. </label>
  23. <label class="label-normal">
  24. <input type="radio" name="radio" id="radio-2" required>
  25. No
  26. </label>
  27. </div>
  28.  
  29. <input type="submit" class="button" value="Submit">
  30. </form>

2. Copy the following CSS code into your stylesheet. These styles ensure a visually appealing and user-friendly form. You can customize the styles according to your website’s design.

  1. body {
  2. font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
  3. font-size: 112.5%;
  4. }
  5.  
  6. /**
  7. * Form Styles
  8. */
  9.  
  10. form{
  11. background: #fff;
  12. padding: 12px;
  13. }
  14. label {
  15. display: block;
  16. font-weight: bold;
  17. margin-bottom: 0.5em;
  18. }
  19.  
  20. .label-normal {
  21. font-weight: normal;
  22. }
  23.  
  24. .description-date {
  25. color: #808080;
  26. font-size: 0.8em;
  27. font-weight: normal;
  28. }
  29.  
  30. .supports-date .description-date {
  31. display: none;
  32. }
  33.  
  34. input,
  35. select {
  36. display: inline-block;
  37. font-size: 1em;
  38. margin-bottom: 1em;
  39. padding: 0.25em 0.5em;
  40. width: 100%;
  41. box-sizing: border-box;
  42. }
  43.  
  44. [type="checkbox"],
  45. [type="radio"] {
  46. margin-bottom: 0.5em;
  47. width: auto;
  48. }
  49.  
  50. .button {
  51. background-color: #0088cc;
  52. border: 1px solid #0088cc;
  53. border-radius: 1px;
  54. color: #ffffff;
  55. display: inline-block;
  56. font-size: 0.9375em;
  57. font-weight: normal;
  58. line-height: 1.2;
  59. margin-right: 0.3125em;
  60. margin-bottom: 0.3125em;
  61. padding: 0.5em 0.6875em;
  62. width: auto;
  63. }
  64.  
  65. .button:active,
  66. .button:focus,
  67. .button:hover {
  68. background-color: #005580;
  69. border-color: #005580;
  70. color: #ffffff;
  71. text-decoration: none;
  72. }
  73.  
  74. .button:active {
  75. box-shadow: inset 0 0.15625em 0.25em rgba(0, 0, 0, 0.15), 0 1px 0.15625em rgba(0, 0, 0, 0.05);
  76. }
  77.  
  78. /**
  79. * Errors
  80. */
  81. .error {
  82. border-color: red;
  83. }
  84.  
  85. .error-message {
  86. color: red;
  87. font-style: italic;
  88. margin-bottom: 1em;
  89. }

3. Finally, copy and paste the JavaScript code at the end of your HTML file or include it in a separate script file. This code adds the “novalidate” attribute to your form, disabling native HTML5 validation. It then implements custom validation logic for each field, showing error messages on blur and preventing form submission if errors exist.

  1. // Add the novalidate attribute when the JS loads
  2. var forms = document.querySelectorAll('.validate');
  3. for (var i = 0; i < forms.length; i++) {
  4. forms[i].setAttribute('novalidate', true);
  5. }
  6.  
  7.  
  8. // Validate the field
  9. var hasError = function (field) {
  10.  
  11. // Don't validate submits, buttons, file and reset inputs, and disabled fields
  12. if (field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') return;
  13.  
  14. // Get validity
  15. var validity = field.validity;
  16.  
  17. // If valid, return null
  18. if (validity.valid) return;
  19.  
  20. // If field is required and empty
  21. if (validity.valueMissing) return 'Please fill out this field.';
  22.  
  23. // If not the right type
  24. if (validity.typeMismatch) {
  25.  
  26. // Email
  27. if (field.type === 'email') return 'Please enter an email address.';
  28.  
  29. // URL
  30. if (field.type === 'url') return 'Please enter a URL.';
  31.  
  32. }
  33.  
  34. // If too short
  35. if (validity.tooShort) return 'Please lengthen this text to ' + field.getAttribute('minLength') + ' characters or more. You are currently using ' + field.value.length + ' characters.';
  36.  
  37. // If too long
  38. if (validity.tooLong) return 'Please shorten this text to no more than ' + field.getAttribute('maxLength') + ' characters. You are currently using ' + field.value.length + ' characters.';
  39.  
  40. // If number input isn't a number
  41. if (validity.badInput) return 'Please enter a number.';
  42.  
  43. // If a number value doesn't match the step interval
  44. if (validity.stepMismatch) return 'Please select a valid value.';
  45.  
  46. // If a number field is over the max
  47. if (validity.rangeOverflow) return 'Please select a value that is no more than ' + field.getAttribute('max') + '.';
  48.  
  49. // If a number field is below the min
  50. if (validity.rangeUnderflow) return 'Please select a value that is no less than ' + field.getAttribute('min') + '.';
  51. // If pattern doesn't match
  52. if (validity.patternMismatch) {
  53.  
  54. // If pattern info is included, return custom error
  55. if (field.hasAttribute('title')) return field.getAttribute('title');
  56.  
  57. // Otherwise, generic error
  58. return 'Please match the requested format.';
  59.  
  60. }
  61.  
  62. // If all else fails, return a generic catchall error
  63. return 'The value you entered for this field is invalid.';
  64.  
  65. };
  66.  
  67.  
  68. // Show an error message
  69. var showError = function (field, error) {
  70.  
  71. // Add error class to field
  72. field.classList.add('error');
  73. // If the field is a radio button and part of a group, error all and get the last item in the group
  74. if (field.type === 'radio' && field.name) {
  75. var group = document.getElementsByName(field.name);
  76. if (group.length > 0) {
  77. for (var i = 0; i < group.length; i++) {
  78. // Only check fields in current form
  79. if (group[i].form !== field.form) continue;
  80. group[i].classList.add('error');
  81. }
  82. field = group[group.length - 1];
  83. }
  84. }
  85.  
  86. // Get field id or name
  87. var id = field.id || field.name;
  88. if (!id) return;
  89.  
  90. // Check if error message field already exists
  91. // If not, create one
  92. var message = field.form.querySelector('.error-message#error-for-' + id );
  93. if (!message) {
  94. message = document.createElement('div');
  95. message.className = 'error-message';
  96. message.id = 'error-for-' + id;
  97. // If the field is a radio button or checkbox, insert error after the label
  98. var label;
  99. if (field.type === 'radio' || field.type ==='checkbox') {
  100. label = field.form.querySelector('label[for="' + id + '"]') || field.parentNode;
  101. if (label) {
  102. label.parentNode.insertBefore( message, label.nextSibling );
  103. }
  104. }
  105.  
  106. // Otherwise, insert it after the field
  107. if (!label) {
  108. field.parentNode.insertBefore( message, field.nextSibling );
  109. }
  110.  
  111. }
  112. // Add ARIA role to the field
  113. field.setAttribute('aria-describedby', 'error-for-' + id);
  114.  
  115. // Update error message
  116. message.innerHTML = error;
  117.  
  118. // Show error message
  119. message.style.display = 'block';
  120. message.style.visibility = 'visible';
  121.  
  122. };
  123.  
  124.  
  125. // Remove the error message
  126. var removeError = function (field) {
  127.  
  128. // Remove error class to field
  129. field.classList.remove('error');
  130. // Remove ARIA role from the field
  131. field.removeAttribute('aria-describedby');
  132.  
  133. // If the field is a radio button and part of a group, remove error from all and get the last item in the group
  134. if (field.type === 'radio' && field.name) {
  135. var group = document.getElementsByName(field.name);
  136. if (group.length > 0) {
  137. for (var i = 0; i < group.length; i++) {
  138. // Only check fields in current form
  139. if (group[i].form !== field.form) continue;
  140. group[i].classList.remove('error');
  141. }
  142. field = group[group.length - 1];
  143. }
  144. }
  145.  
  146. // Get field id or name
  147. var id = field.id || field.name;
  148. if (!id) return;
  149.  
  150. // Check if an error message is in the DOM
  151. var message = field.form.querySelector('.error-message#error-for-' + id + '');
  152. if (!message) return;
  153.  
  154. // If so, hide it
  155. message.innerHTML = '';
  156. message.style.display = 'none';
  157. message.style.visibility = 'hidden';
  158.  
  159. };
  160.  
  161.  
  162. // Listen to all blur events
  163. document.addEventListener('blur', function (event) {
  164.  
  165. // Only run if the field is in a form to be validated
  166. if (!event.target.form.classList.contains('validate')) return;
  167.  
  168. // Validate the field
  169. var error = hasError(event.target);
  170. // If there's an error, show it
  171. if (error) {
  172. showError(event.target, error);
  173. return;
  174. }
  175.  
  176. // Otherwise, remove any existing error message
  177. removeError(event.target);
  178.  
  179. }, true);
  180.  
  181.  
  182. // Check all fields on submit
  183. document.addEventListener('submit', function (event) {
  184.  
  185. // Only run on forms flagged for validation
  186. if (!event.target.classList.contains('validate')) return;
  187.  
  188. // Get all of the form elements
  189. var fields = event.target.elements;
  190.  
  191. // Validate each field
  192. // Store the first field with an error to a variable so we can bring it into focus later
  193. var error, hasErrors;
  194. for (var i = 0; i < fields.length; i++) {
  195. error = hasError(fields[i]);
  196. if (error) {
  197. showError(fields[i], error);
  198. if (!hasErrors) {
  199. hasErrors = fields[i];
  200. }
  201. }
  202. }
  203.  
  204. // If there are errrors, don't submit form and focus on first element with error
  205. if (hasErrors) {
  206. event.preventDefault();
  207. hasErrors.focus();
  208. }
  209.  
  210. // Otherwise, let the form submit normally
  211. // You could also bolt in an Ajax form submit process here
  212.  
  213. }, false);

If needed, customize the validation rules in the JavaScript code to match your specific requirements. You can adjust the error messages, validation patterns, and field-specific criteria based on your application’s needs.

That’s all! hopefully, you have successfully created a functionality in JavaScript to prevent form submit until validation process. If you have any questions or suggestions, feel free to comment below.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About CodeHim

Free Web Design Code & Scripts - CodeHim is one of the BEST developer websites that provide web designers and developers with a simple way to preview and download a variety of free code & scripts. All codes published on CodeHim are open source, distributed under OSD-compliant license which grants all the rights to use, study, change and share the software in modified and unmodified form. Before publishing, we test and review each code snippet to avoid errors, but we cannot warrant the full correctness of all content. All trademarks, trade names, logos, and icons are the property of their respective owners... find out more...

Please Rel0ad/PressF5 this page if you can't click the download/preview link

X