Learn Magento 2 form Validation

https://www.thecoachsmb.com/a-complete-guide-on-magento-2-form-validation/

and

https://magecomp.com/blog/create-custom-form-in-magento-2-frontend/

 

 

Here is simple form example that make an ajax call

<?php
/** @var \Mageleap\Customform\Block\Index\Index $block */






?>
<div class="row"></div>

<form id="your-form-id" method="post" action="test.php" data-hasrequired="<?= $escaper->escapeHtmlAttr(__('* Required Fields')) ?>">

<div class="row">

<div class="col-md-6">
<div class="field city required">
<label class="label" for="city">
<span><?= /* @noEscape */ ('city') ?></span>
</label>
<div class="control">
<input type="text" name="city" title="<?= $escaper->escapeHtmlAttr(__('City')) ?>" class="input-text required-entry" id="city">
</div>
</div>
</div>
<div class="col-md-6">
<div class="field zip required">
<label class="label" for="zip">
<span>postcode</span>
</label>
<div class="control">
<input type="text" name="postcode" title="" class="input-text required-entry validate-zip-international" id="zip">
<?= /* @noEscape */ $secureRenderer->renderStyleAsTag("display: none;", 'div.message.warning') ?>
</div>
</div>
</div>

</div>
<div class="row">
<div class="col-md-6">

</div>
</div>
<div class="actions-toolbar">
<div class="primary">
<button class="action save primary" type="submit" name="submit" value="submit" title="<?= $escaper->escapeHtmlAttr(__('Save Address')) ?>">
<span><?= $escaper->escapeHtml(__('Save Address')) ?></span>
</button>
</div>
<div class="primary">
<button class="action save primary cancel" title="Cancel" id="cancelButtonadd">
<span>Cancel</span>
</button>
</div>
</div>



<div class="field">
<label for="country" class="label"><span><?php /* @escapeNotVerified */ echo __('Country') ?></span></label>
<div class="control">
<select name="country" id="country" class="input-select" data-validate="{required:true}">
<?php foreach ($block->getCountries() as $country): ?>
<option value="<?php echo $country['value']; ?>"><?php echo $country['label']; ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="field">
<div class="field">
<label for="state" class="label"><span><?php /* @escapeNotVerified */ echo __('State') ?></span></label>
<div class="control">
<select name="state" id="state" class="input-select" data-validate="{required:true}">
<!-- State options will be loaded dynamically via JavaScript -->
</select>
</div>
</div>
</div>
</form>



<script type="text/x-magento-init">
{
"#country": {
"change": "customForm"
}
}
</script>


<script type="text/x-magento-init">
{
"#your-form-id": {
"validation": {}
}
}
</script><script type="text/x-magento-init">
{
"#country": {
"change": "customForm"
}
}
</script>

<form method="post" action="index.phtml">
<select name="one" id="one">
<option value=""></option>
<option value="1">1</option>
<option value="2">2</option>
</select>
<input type="text" id="t" name="t" value=""/>
</form>
<script>
require(['jquery', 'mage/url'], function ($, urlBuilder) {
$(document).ready(function () {
$('#t').on('click', function () {
// Assigning the jQuery object representing the element with id 't' to the variable 'any'
var any = $('#t');

// Now you can use the variable 'any' to perform any further actions
// For example, you can get the value of the input field and alert it
var inputValue = any.val();
alert('The value of the input field is: ' + inputValue);
});
});
});

</script>
<script>
require(['jquery', 'mage/url'], function($, urlBuilder) {
$(document).ready(function() {
$('#country').on('change', function() {
var countryId = $(this).val();
if (countryId) {

var url = urlBuilder.build('mageleap_customform/index/getstates', { country_id: countryId });
$.ajax({
url: url,
type: 'post',
dataType: 'json',
data: { country_id: countryId }, // Add this line to pass country ID in data
success: function (response) {
$('#state').empty();
$.each(response.states, function (key, value) {
$('#state').append($('<option>', {
value: key,
text: value
}));
});
}
});
} else {
alert('Please select a country.');
}
});
});
});
</script>

jQuery rules:

RulesDescription
requiredThis is a required field
remotePlease fix this field
emailPlease enter a valid email address
urlPlease enter a valid URL
datePlease enter a valid date
dateISOPlease enter a valid date (ISO)
numberPlease enter a valid number
digitsPlease enter only digits
creditcardPlease enter a valid credit card number
equalToPlease enter the same value again
maxlengthPlease enter no more than {0} characters.
minlengthPlease enter at least {0} characters.
rangelengthPlease enter a value between {0} and {1} characters long.
rangePlease enter a value between {0} and {1}.
maxPlease enter a value less than or equal to {0}.
minPlease enter a value greater than or equal to {0}.

 

Magento rules:

RulesDescription
max-wordsPlease enter {0} words or less
min-wordsPlease enter at least {0} words
range-wordsPlease enter between {0} and {1} words
letters-with-basic-puncLetters or punctuation only please
alphanumericLetters, numbers, spaces or underscores only please
letters-onlyLetters only please
no-whitespaceNo white space please
zip-rangeYour ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx
integerA positive or negative non-decimal number please
vinUSThe specified vehicle identification number (VIN) is invalid
dateITAPlease enter a correct date
dateNLVul hier een geldige datum in
timePlease enter a valid time, between 00:00 and 23:59
time12hPlease enter a valid time, between 00:00 am and 12:00 pm
phoneUSPlease specify a valid phone number
phoneUKPlease specify a valid phone number
mobileUKPlease specify a valid mobile number
stripped-min-lengthPlease enter at least {0} characters
validate-no-utf8mb4-charactersPlease remove invalid characters: {0}
credit-card-typesPlease enter a valid credit card number
ipv4Please enter a valid IP v4 address
ipv6Please enter a valid IP v6 address
patternInvalid format
allow-container-classNamebool
validate-no-html-tagsHTML tags are not allowed
validate-selectPlease select an option
validate-no-emptyEmpty Value
validate-alphanum-with-spacesPlease use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field
validate-dataPlease use only letters (a-z or A-Z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter
validate-streetPlease use only letters (a-z or A-Z), numbers (0-9), spaces and “#” in this field
validate-phoneStrictPlease enter a valid phone number. For example (123) 456-7890 or 123-456-7890
validate-phoneLaxPlease enter a valid phone number. For example (123) 456-7890 or 123-456-7890
validate-faxPlease enter a valid fax number (Ex: 123-456-7890)
validate-emailPlease enter a valid email address (Ex: johndoe@domain.com)
validate-emailSenderPlease enter a valid email address (Ex: johndoe@domain.com)
validate-passwordPlease enter 6 or more characters. Leading and trailing spaces will be ignored
validate-admin-passwordPlease enter 7 or more characters, using both numeric and alphabetic
validate-customer-passwordMinimum length of this field must be equal or greater than %1 symbols. Leading and trailing spaces will be ignored.Minimum of different classes of characters in password is %1. Classes of characters: Lower Case, Upper Case, Digits, Special Characters
validate-urlPlease enter a valid URL. Protocol is required (http://, https:// or ftp://)
validate-clean-urlPlease enter a valid URL. For example http://www.example.com or www.example.com
validate-xml-identifierPlease enter a valid XML-identifier (Ex: something_1, block5, id-4)
validate-ssnPlease enter a valid social security number (Ex: 123-45-6789)
validate-zip-usPlease enter a valid zip code (Ex: 90602 or 90602-1234)
validate-date-auPlease use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006
validate-currency-dollarPlease enter a valid $ amount. For example $100.00
validate-not-negative-numberPlease enter a number 0 or greater in this field
validate-zero-or-greaterPlease enter a number 0 or greater in this field
validate-greater-than-zeroPlease enter a number greater than 0 in this field
validate-css-lengthPlease input a valid CSS-length (Ex: 100px, 77pt, 20em, .5ex or 50%)
validate-numberPlease enter a valid number in this field
required-numberPlease enter a valid number in this field
validate-number-rangeThe value is not within the specified range
validate-digitsPlease enter a valid number in this field
validate-digits-rangeThe value is not within the specified range
validate-rangeThe value is not within the specified range
validate-alphaPlease use letters only (a-z or A-Z) in this field
validate-codePlease use only letters (a-z), numbers (0-9) or underscore (_) in this field, and the first character should be a letter
validate-alphanumPlease use only letters (a-z or A-Z) or numbers (0-9) in this field. No spaces or other characters are allowed
validate-datePlease enter a valid date
validate-date-rangeMake sure the To Date is later than or the same as the From Date
validate-cpasswordPlease make sure your passwords match
validate-identifierPlease enter a valid URL Key (Ex: “example-page”, “example-page.html” or “anotherlevel/example-page”)
validate-zip-internationalPlease enter a valid zip code
validate-one-requiredPlease select one of the options above
validate-statePlease select State/Province
required-filePlease select a file
validate-ajax-errorbool
validate-optional-datetimeThe field isn’t complete
validate-required-datetimeThis is a required field
validate-one-required-by-namePlease select one of the options
less-than-equals-toPlease enter a value less than or equal to %s
greater-than-equals-toPlease enter a value greater than or equal to %s
validate-emailsPlease enter valid email addresses, separated by commas. For example, johndoe@domain.com, johnsmith@domain.com
validate-cc-type-selectCard type does not match credit card number
validate-cc-numberPlease enter a valid credit card number
validate-cc-typeCredit card number does not match credit card type
validate-cc-expIncorrect credit card expiration date
validate-cc-cvnPlease enter a valid credit card verification number
validate-cc-ukssPlease enter issue number or start date for switch/solo card type
validate-lengthPlease enter less or equal than %1 symbols..replace(‘%1’, length);Please enter more or equal than %1 symbols..replace(‘%1’, length)
required-entryThis is a required field
not-negative-amountPlease enter positive number in this field
validate-per-page-value-listPlease enter a valid value, ex: 10,20,30
validate-per-page-valuePlease enter a valid value from list
validate-new-passwordPlease enter 6 or more characters. Leading and trailing spaces will be ignored
required-if-not-specifiedThis is a required field
required-if-all-sku-empty-and-file-not-loadedPlease enter valid SKU key
required-if-specifiedThis is a required field
required-number-if-specifiedPlease enter a valid number
datetime-validationThis is required field
required-text-swatch-entryAdmin is a required field in each row
required-visual-swatch-entryAdmin is a required field in each row
required-dropdown-attribute-entryAdmin is a required field in each row
validate-item-quantityPlease enter a quantity greater than 0;The fewest you may purchase is %1;

The maximum you may purchase is %1;

You can buy this product only in quantities of %1 at a time

password-not-equal-to-user-namepassword-not-equal-to-user-nam

Magento 2 default  You can see the list of jquery rules in the lib/web/jquery/jquery.validate.js file and see the list of Magento rules in the lib/web/mage/validation.js file.

 

 

 

 

Add this code in phtml file

<div class="container">
<div class="row">
<form id="custom-form" action="<?= $block->getFormActionUrl(); ?>" method="post" enctype="multipart/form-data" data-mage-init='{"validation": {}}'>
<fieldset class="fieldset">
<!-- Email Field -->
<div class="field">
<label for="email" class="label"><span>Email</span></label>
<div class="control">
<input type="email" name="email" id="email" class="input-text" data-validate="{required:true, 'validate-email':true}" />
</div>
</div>

<!-- Date of Birth Field -->
<div class="field">
<label for="dob" class="label"><span>Date of Birth</span></label>
<div class="control">
<input type="date" name="dob" id="dob" class="input-text" data-validate="{required:true}" />
</div>
</div>

<!-- Country Dropdown Field -->
<div class="field">
<label for="country" class="label"><span>Country</span></label>
<div class="control">
<select name="country" id="country" class="select" data-validate="{required:true}">
<option value="">Select Country</option>
<option value="US">United States</option>
<option value="CA">Canada</option>
<!-- Add more countries as needed -->
</select>
</div>
</div>

<!-- Password Field -->
<div class="field">
<label for="password" class="label"><span>Password</span></label>
<div class="control">
<input type="password" name="password" id="password" class="input-text" data-validate="{required:true, 'min-length':6}" />
</div>
</div>

<!-- Checkbox Field -->
<div class="field choice">
<label for="terms" class="label"><span>Accept Terms</span></label>
<div class="control">
<input type="checkbox" name="terms" id="terms" value="1" data-validate="{required:true}" />
</div>
</div>

<!-- File Upload Field -->
<div class="field">
<label for="fileupload" class="label"><span>Upload File</span></label>
<div class="control">
<input type="file" name="fileupload" id="fileupload" class="input-file" data-validate="{required:true}" />
</div>
</div>

<!-- Time Field -->
<div class="field">
<label for="time" class="label"><span>Time</span></label>
<div class="control">
<input type="time" name="time" id="time" class="input-text" data-validate="{required:true}" />
</div>
</div>

<!-- ZIP Code Field -->
<div class="field">
<label for="zipcode" class="label"><span>ZIP Code</span></label>
<div class="control">
<input type="text" name="zipcode" id="zipcode" class="input-text" data-validate="{required:true, 'validate-zip-international':true}" />
</div>
</div>

<!-- URL Field -->
<div class="field">
<label for="url" class="label"><span>Website URL</span></label>
<div class="control">
<input type="url" name="url" id="url" class="input-text" data-validate="{required:true, 'validate-url':true}" />
</div>
</div>

<!-- Number Field -->
<div class="field">
<label for="number" class="label"><span>Number</span></label>
<div class="control">
<input type="number" name="number" id="number" class="input-text" data-validate="{required:true, 'validate-number':true}" />
</div>
</div>

<!-- Digits Field -->
<div class="field">
<label for="digits" class="label"><span>Digits</span></label>
<div class="control">
<input type="text" name="digits" id="digits" class="input-text" data-validate="{required:true, 'validate-digits':true}" />
</div>
</div>

<!-- Credit Card Field -->
<div class="field">
<label for="cc" class="label"><span>Credit Card</span></label>
<div class="control">
<input type="text" name="cc" id="cc" class="input-text" data-validate="{required:true, 'validate-cc-number':true}" />
</div>
</div>

<!-- Submit Button -->
<div class="actions-toolbar">
<button type="submit" class="action submit primary">
<span>Submit</span>
</button>
</div>
</fieldset>
</form>
</div>
</div>

 

This controller to save and process the form

<?php

namespace Anees\Blog\Controller\Post;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Exception\LocalizedException;

class Save extends Action
{
/**
* Execute method
*/
public function execute()
{
$post = $this->getRequest()->getPostValue();


if (!$post) {
return $this->resultFactory->create(ResultFactory::TYPE_REDIRECT)->setUrl($this->_redirect->getRefererUrl());
}

try {
// Handle the form submission and validation here
// Example: $email = $post['email'];

$this->messageManager->addSuccessMessage(__('Form submitted successfully.'));
} catch (LocalizedException $e) {
$this->messageManager->addErrorMessage($e->getMessage());
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('An error occurred while submitting the form.'));
}

return $this->resultFactory->create(ResultFactory::TYPE_REDIRECT)->setUrl($this->_redirect->getRefererUrl());
}
}

This is block class which define the conroller to save form.

<?php
/**
* Copyright © All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Anees\Blog\Block\Index;

class Index extends \Magento\Framework\View\Element\Template
{

/**
* Constructor
*
* @param \Magento\Framework\View\Element\Template\Context $context
* @param array $data
*/
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
array $data = []
) {
parent::__construct($context, $data);
}

public function getFormActionUrl(){

return $this->getUrl('blog/post/save');
}
}

You will see this after adding code.

 

Initiating validation

 

<form id="my-form" data-mage-init='{"validation": {}}'>
...
</form>
 
<script type="text/x-magento-init">
{
"#my-form": {
"validation": {}
}
}
</script>

 

Defining validation rules

 

There are couple of ways to define validation rules for a form field.

As a data-validate attribute

<input id="field-1" ... data-validate='{"required":true}'/>

As a data-validate attribute with arguments

<input id="field-1" ... data-validate='{"required":true, "minlength":10}'/>

As an attribute

<input id="field-1" ... required="true"/>

As an attribute with arguments

<input id="field-1" ... required="true" minlength="15"/>

As a class name

<input id="field-1" ... class="input-text required-entry"/>

As a class name with arguments

<input id="field-1" ... class="input-text required-entry" minlength="15"/>

Using data-mage-init

<form ... data-mage-init='{"validation": {"rules": {"field-1": {"required":true}}}}'>
...
</form>

Using data-mage-init with arguments

<form ... data-mage-init='{"validation": {"rules": {"field-1": {"required":true, "minlength":20}}}}'>
...
</form>

Examples

Adding the validation for a form

Here are examples of all available ways of validating the form fields.


 
<form class="form" id="my-form" method="post" data-mage-init='{"validation":{"rules": {"field-4": {"required":true}}}}'>
<fieldset class="fieldset">
<div class="field name required">
<label class="label" for="field-1"><span>Field 1 (using data-validate)</span></label>
<div class="control">
<input name="field-1" id="field-1" title="Field 1" value="" class="input-text" type="text" data-validate='{"required":true, "url": true}'/>
</div>
</div>
<div class="field name required">
<label class="label" for="field-2"><span>Field 2 (using attribute)</span></label>
<div class="control">
<input name="field-2" id="field-2" title="Field 2" value="" class="input-text" type="text" required="true"/>
</div>
</div>
<div class="field name required">
<label class="label" for="field-3"><span>Field 3 (using classname)</span></label>
<div class="control">
<input name="field-3" id="field-3" title="Field 3" value="" type="text" class="input-text required-entry"/>
</div>
</div>
<div class="field name required">
<label class="label" for="field-4"><span>Field 4 (using data-mage-init)</span></label>
<div class="control">
<input name="field-4" id="field-4" title="Field 4" value="" class="input-text" type="text"/>
</div>
</div>
</fieldset>
<div class="actions-toolbar">
<div class="primary">
<button type="submit" title="Submit" class="action submit primary">
<span>Submit</span>
</button>
</div>
</div>
</form>

Get more

Here is detailed valudation rules list

https://developer.adobe.com/commerce/frontend-core/guide/validations/rule-list/