Normally, the browser’s HTML5 constraint validation API allows us to set a custom message with setCustomValidity()
. However, that only allows text, no HTML. This example shows you how to add an HTML link to the custom validity error message.
This example is specifically for the WooCommerce product quantity input field, and it specifically adds a custom message when the quantity entered exceeds the max allowed. You can modify this, as needed.
The basic method is this:
- Stop the built-in browser form validation for the Add to cart form.
- Add your own custom JavaScript validation for the quantity input field.
- Create your own custom error message to show if validation fails. This allows you to add HTML to the error message. This custom message will have to be styled, so I’ve added some CSS styles on lines 158–163.
You must edit the error message on line 34 to suit your needs. In this example, the error message is:
Limit of {MAX-NUMBER} per order. Please go here.
…in which “go here” is a link.
The HTML for the link on line 34 looks like this:
<a href=\'#\'>go here</a>
- Change the
#
to the URL address of the page which you want to link to. Leave the backslashes and single quotes as they are. - Change
go here
to the text for the link.
Here is the entire code, and it goes in your functions.
/** * Customize the browser's default constraint validation message for exceeding the input max */ function isa_wc_max_qty_custom_html_error_msg() { /* Add JS to frontend wherever woocommerce.js is loaded. */ wp_add_inline_script( 'woocommerce', 'window.onload = function(){ var productForm = document.querySelector( "form.cart" ); var cartForm = document.querySelector( "form.woocommerce-cart-form" ); // Custom validation for the quantity field var qtyHasError = function (field) { // Get validity var validity = field.validity; // If valid, return null if (validity.valid) return; // If number input isn"t a number if (validity.badInput) return "Please enter a number."; // If a number value doesn"t match the step interval if (validity.stepMismatch) return "Please select a valid value."; // If a number field is over the max if (validity.rangeOverflow) { var max = field.getAttribute( "max" ); return "Limit of " + max + " per order. Please <a href=\'#\'>go here</a>."; } // If a number field is below the min if (validity.rangeUnderflow) return "Please select a value that is no less than " + field.getAttribute("min") + "."; // If all else fails, return a generic catchall error return "The value you entered for this field is invalid."; }; // Show the error message var qtyShowError = function (field, error) { // Add error class to field field.classList.add("error"); // Get field id or name var id = field.id || field.name; if (!id) return; // Check if error message field already exists // If not, create one var message = field.form.querySelector(".qty-error-message#error-for-" + id ); if (!message) { message = document.createElement("div"); message.className = "qty-error-message"; message.id = "error-for-" + id; field.parentNode.insertBefore( message, field.nextSibling ); } // Add ARIA role to the field field.setAttribute("aria-describedby", "error-for-" + id); // Update error message message.innerHTML = error; // Show error message message.style.display = "block"; message.style.visibility = "visible"; }; // Remove the error message var qtyRemoveError = function (field) { // Remove error class to field field.classList.remove("error"); // Remove ARIA role from the field field.removeAttribute("aria-describedby"); // Get field id or name var id = field.id || field.name; if (!id) return; // Check if an error message is in the DOM var message = field.form.querySelector(".qty-error-message#error-for-" + id + ""); if (!message) return; // If so, hide it message.innerHTML = ""; message.style.display = "none"; message.style.visibility = "hidden"; }; // Validate the quantity field function validateQtyonBlur( event ) { // Validate the field var error = qtyHasError(event.target); // If there is an error, show it if (error) { qtyShowError(event.target, error); return; } // Otherwise, remove any existing error message qtyRemoveError(event.target); } if ( productForm ) { // Stop the built-in browser form validation for Add to Cart form productForm.setAttribute("novalidate", true); // If there is an error, do not submit form productForm.addEventListener("submit", function (event) { if ( qtyHasError( event.target.quantity ) ) { event.preventDefault(); } }, false); } // Stop the built-in browser form validation for Update Cart form if ( cartForm ) { cartForm.setAttribute("novalidate", true); } // Do custom validation on quantity field var quantity = document.querySelector( "form.cart .qty" ); var cartQuantity = document.querySelector( "form.woocommerce-cart-form .qty" ); if ( quantity ) { // quantity input on single product page quantity.addEventListener( "blur", validateQtyonBlur, true ); } if ( cartQuantity ) { // quantity input on cart page cartQuantity.addEventListener( "blur", validateQtyonBlur, true ); } };' ); /* Add CSS to frontend wherever woocommerce.js is loaded. */ wp_add_inline_style( 'woocommerce-layout', ' .qty-error-message { padding:1px; color:#D8000C;background:#ffd2d2; border:1px solid #D8000C; border-radius: 5px; } ' ); } add_action( 'wp_enqueue_scripts', 'isa_wc_max_qty_custom_html_error_msg', 9999 );
Jaime
May 29th, 2019 at 4:35 am
Fantastic!