0

How can I add Magento custom validation for month and date text box? These two are input text box user can enter the number and I have to validate it via custom validation. Don't want a calender.

<div class="field date field-dob">
                    <label class="label" for="dob"><span>Your Birthday</span></label>
                    <div class="input-box customer-dob">
                        <div class="dob-month">
                            <input type="text" id="month" name="month" value="12" title="Month" class="input-text validate-custom">
                            <label for="month">MM</label>
                        </div><div class="dob-day">
                            <input type="text" id="day" name="day" value="12" title="Day" class="input-text validate-custom">
                            <label for="day">DD</label>
                        </div><div class="dob-year" style="display:none;">
                            <input value="1900" type="text" id="year" name="year" title="Year" class="input-text validate-custom" autocomplete="off">
                            <label for="year">YYYY</label>
                        </div>    <div class="dob-full" style="display:none;">
                            <input type="hidden" id="dob" name="dob">
                        </div>

                        <div class="validation-advice" style="display:none;"></div>
                    </div>

                </div>

script

<script type="text/javascript">
  //<![CDATA[
     var customer_dob = new Varien.DOB('.customer-dob', false, 
   '%m/%e/%Y');
   //]]>
 </script>

This code didn't work for me.

1

Add Magento custom validation to a form field using adding a new rule using $.validator.addMethod

using $.validator.addMethod we can create number of custom rules and via class name we can access those custom rules.

so back to the question, need of question is without using calendar validate input fields like days/month/year.

so assuming where you adding these days/month/year fields that wrap with form tag, In this form magento default validation added data-mage-init='{"validation":{}}' or via js.

create all days/month/year fields under form or add below html code

<div class="field date field-dob"  data-mage-init='{
        "Vendor_Module/js/custom-validation-dob":{
            "day" : "[name=\"day\"]",
            "month" : "[name=\"month\"]",
            "year" : "[name=\"year\"]",
            "classPrefix": "custom-dob",
            "maxYearDiff": 150
        }
    }'>
    <label class="label" for="dob">
        <span><?= __('Your Birthday'); ?></span>
    </label>
    <div class="input-box customer-dob">
         <div class="dob-day">
             <label for="day"><?= __('DD'); ?></label>
            <input type="text" id="day" name="day"  title="<?= __('Day'); ?>" class="input-text required-entry" autocomplete="off">
        </div>

        <div class="dob-month">
             <label for="month"><?= __('MM'); ?></label>
            <input type="text" id="month" name="month" title="<?= __('Month'); ?>" class="input-text required-entry" autocomplete="off">
        </div>

        <div class="dob-year">
            <label for="year"><?= __('YYYY'); ?></label>
            <input type="text" id="year" name="year" title="<?= __('Year'); ?>" class="input-text required-entry" autocomplete="off">
        </div>    
    </div>
</div>

Alter or update the HTML as your need expect name attribute of input field. if need to modify name attribute too then do same change in

data-mage-init='{
    "Vendor_Module/js/custom-validation-dob":{
        "day" : "[name=\"day\"]",
        "month" : "[name=\"month\"]",
        "year" : "[name=\"year\"]",
        "classPrefix": "custom-dob",
        "maxYearDiff": 150
    }
}'

as well with respective fields.

Now create a js file custom-validation-dob.js under your module something like that Vendor/Module/view/frontend/web/js/custom-validation-dob.js the paste below js code

define([
    'jquery',   
    'jquery/ui',
    'jquery/validate',
    'mage/translate'
], function($){
    'use strict';

    var enterValueIsNumeric = function (input) {
       return (input - 0) == input && input.length > 0;
    }

    return function(config, element) {
        var dayObj = $(element).find(config.day || '[name="day"]');
        var monthObj = $(element).find(config.month || '[name="month"]');
        var yearObj = $(element).find(config.year || '[name="year"]');        
        var classPrefix = config.classPrefix || 'custom';
        var maxYearDiff = config.maxYearDiff ||  100; // max limit for year gap

        $.validator.addMethod(
            classPrefix+"-day-validate",
            function(value, element) {
                var result = false,
                    validatorObj = this,
                    isElementOptional = this.optional(element),
                    days = 31; // just to assume no value set on year and month fields

                var year = yearObj.val();
                var month = monthObj.val();

                var currentDateObj = new Date();
                var maxMonth = currentDateObj.getMonth() + 1;
                var maxYear = currentDateObj.getFullYear();
                var currentDay = currentDateObj.getDate();

                var message = $.mage.__("Please enter valid day value in this field.");


                if(enterValueIsNumeric(value)) {
                    if(year && month){ //Checks days in the specific month with year
                        days = new Date(year, month, 0).getDate();
                    }

                    result = days >= value;
                    if(result && year == maxYear && month == maxMonth) { // for current year & month
                        result = currentDay >= value;
                        message = $.mage.__("Entered day value will be less then or equal to %1 that is current day because Entered Year and Month value respectively equal to current year and month value.").replace('%1', currentDay);
                    }
                } 

                if (!result) {
                    validatorObj.customDayMessage = message;
                }                
                return isElementOptional || result;
            }, function () {
                return this.customDayMessage;
            }            
        );

        $.validator.addMethod(
            classPrefix+"-month-validate",
            function(value, element) {
                var result = false,
                    validatorObj = this,
                    isElementOptional = this.optional(element);
                var year = yearObj.val();

                var currentDateObj = new Date();
                var maxMonth = currentDateObj.getMonth() + 1;
                var maxYear = currentDateObj.getFullYear();

                var message = $.mage.__("Please enter valid month value in this field.");
                if(enterValueIsNumeric(value)) {
                    result = ( value >= 1 && value <= 12);
                    if(result && year == maxYear) { // For current year 
                        result = ( value <= maxMonth);
                        message = $.mage.__("Entered month value will be less then or equal to %1 that is current month because Entered Year value is equal to current year value.").replace('%1', maxMonth);
                    } 
                } 

                if (!result) {
                    validatorObj.customMonthMessage = message;
                }
                return isElementOptional || result; 
            }, function () {
                return this.customMonthMessage;
            }
        );

        $.validator.addMethod(
            classPrefix+"-year-validate",
            function(value, element) {
                var result = false,
                    validatorObj = this,
                    isElementOptional = this.optional(element),
                    prevDateObj = new Date(),
                    currentDateObj = new Date();

                prevDateObj.setFullYear(prevDateObj.getFullYear() - maxYearDiff);
                currentDateObj.setFullYear(currentDateObj.getFullYear());

                var minYear = prevDateObj.getFullYear();
                var maxYear = currentDateObj.getFullYear(); // because DOB value will be less then the current year
                var message = $.mage.__("Please enter valid year value in this field and year value will be in between %1 and %2").replace('%1', minYear).replace('%2', maxYear);

                if(enterValueIsNumeric(value)) {
                    result = (value.length == 4 && value >= minYear && value <= maxYear ); // always be year value in 4 digit
                }

                if (!result) {
                    validatorObj.customYearMessage = message;
                }
                return isElementOptional || result;
            }, function () {
                return this.customYearMessage;
            }

        );     

        // binding class with respective element to apply validation rule properly.
        dayObj.addClass(classPrefix+"-day-validate");
        monthObj.addClass(classPrefix+"-month-validate");
        yearObj.addClass(classPrefix+"-year-validate");
    }
});

using these 2 code set, first html markup and second magento custom js will help to validate calendar like function. and these rules are linked also so proper validation come in picture hope this will match all you expectation mention in question.

Add on -

For future reuse of this custom js with valid name instead of full path, alias the js path with a good name.

So create a requirejs config file requirejs-config.js in your module Vendor/Module/view/frontend/requirejs-config.js if not exist and add below code

var config = {
    "map": {
        "*": {
            "customValidationForDMY": "Vendor_Module/js/custom-validation-dob" // D = Day,M = Month, Y = Year
        }
    }
};

then in above mention html code update

data-mage-init='{
    "Vendor_Module/js/custom-validation-dob":{
        "day" : "[name=\"day\"]",
        "month" : "[name=\"month\"]",
        "year" : "[name=\"year\"]",
        "classPrefix": "custom-dob",
        "maxYearDiff": 150
    }
}'

with

data-mage-init='{
    "customValidationForDMY":{
        "day" : "[name=\"day\"]",
        "month" : "[name=\"month\"]",
        "year" : "[name=\"year\"]",
        "classPrefix": "custom-dob",
        "maxYearDiff": 150
    }
}'

In given sample I used Vendor_Module, In your case this will be change with your respective module name.

Any help will be appreciated.

0

Why don't you try already existing validations? They are already here and ready to use:

For the month field add the classes:

validate-number validate-greater-than-zero less-than-equals-to-12

For the day field add the classes:

validate-number validate-greater-than-zero less-than-equals-to-30

For the year field add the classes:

validate-number greater-than-equals-to-1950 less-than-equals-to-2050

Add data-mage-init='{"validation":{}}' to your form tag.

You can check more here

0

STEP1: You need to data-mage-init attribute in your custom form. Refer below code

<form class="form contact"
      action=""
      id="contact-form"
      method="post"
      data-mage-init='{
    "validation":{},
     "customValidationMethod":{}
}'>
    <div class="field date field-dob">
        <label class="label" for="dob"><span>Your Birthday</span></label>
        <div class="input-box customer-dob">
            <div class="dob-month">
                <input type="text" id="month" name="month" value="29" title="Month" class="input-text validate-custom custom-date">
                <label for="month">MM</label>
            </div><div class="dob-day">
                <input type="text" id="day" name="day" value="2" title="Day" class="input-text validate-custom custom-month">
                <label for="day">DD</label>
            </div><div class="dob-year">
                <input value="2008" type="text" id="year" name="year" title="Year" class="input-text validate-custom custom-year" autocomplete="off">
                <label for="year">YYYY</label>
            </div>    <div class="dob-full" style="display:none;">
                <input type="hidden" id="dob" name="dob">
            </div>
            <div class="validation-advice" style="display:none;"></div>
        </div>
    </div>
    <div class="actions">
        <button class="action subscribe type="submit">
            <span>Submit</span>
        </button>
    </div>
</form>

And add custom-date, custom-month, custom-year classes for respective fields to add logic in validation method.

STEP2: Add requirejs-config.js in your custom module Vendor/Module/view/frontend/requirejs-config.js with following code,

var config = {
    map: {
        "*": {
            customValidationMethod: "Vendor_Module/js/customValidationMethod"
        }
    }
};

STEP3: Place the customValidationMethod.js file in Vendor/Module/view/frontend/web/js/customValidationMethod.js with validation logic

define([
    'jquery',
    'jquery/ui',
    'jquery/validate',
    'mage/translate'
], function($){
    'use strict';

    return function() {
        $.validator.addMethod(
            "custom-date",
            function(value, element) {
                var year = jQuery('.custom-year').val();
                var month = jQuery('.custom-month').val();
                var daysIn = 31;
                if(year && month){
                    //Checks days in the specific month with year
                    daysIn = new Date(year, month, 0).getDate();
                }
                return this.optional(element) || (daysIn >= value);
            },
            $.mage.__("Please enter valid date")
        );

        $.validator.addMethod(
            "custom-month",
            function(value, element) {
                return this.optional(element) || (value >= 1 && value <= 12);
            },
            $.mage.__("Please enter valid month")
        );

        $.validator.addMethod(
            "custom-year",
            function(value, element) {
                //Add your required year
                return this.optional(element) || (value >= 1950 && value <= 2019);
            },
            $.mage.__("Please enter valid year")
        );
    }
});

Please add required class to the input box if the field is required. And don't forgot to run these CLI Commands

php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy -f

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.