(734)545-8017

The Human Element Blog

Form Validation, the Magento way…

Posted Oct 31, 2014 by

Whoa!? huh?Pop quiz hotshot. You have a form on your Magento site. If it’s not filled out correctly, bad stuff will happen. What do you do? What do you do?

Form Validation? huh?

No worries, Magento has a cool built-in system for handling form validation, all you need to do is assign a valid class name to your input field, and pass the form id to VarienForm object.

Let’s take a look at Magento checkout as an example. A quick look at the code for the “Last Name” field in the billing section shows:
Checkout

<div class="field name-lastname">
    <label for="billing:lastname" class="required"><em>*</em>Last Name</label>
    <div class="input-box">
        <input type="text" id="billing:lastname" name="billing[lastname]" value="" title="Last Name" maxlength="255" class="input-text required-entry">
    </div>
</div>

Notice the

class="input-text required-entry"

that’s what prototype looks at to determine whether or not to validate the field. This can be taken further than just “is there stuff in the field?” (required-entry) to maybe something like “are there only numbers in the field?” or “are there only 5 numbers in the field?”

Now take a peek at the code for the email field in checkout

<div class="field">
    <label for="billing:email" class="required"><em>*</em>Email Address</label>
    <div class="input-box">
        <input type="email" autocapitalize="off" autocorrect="off" spellcheck="false" name="billing[email]" id="billing:email" value="" title="Email Address" class="input-text validate-email required-entry">
    </div>
</div>

Here there’s required-entry and also validate-email in the input field class. Starting to see a pattern yet?

Example 1

Let’s say we want to make the “Company” field in the billing section of checkout required. Easy, we just open up the template file and add the correct class name to the field in question.

/app/design/frontend/rwd/enterprise/template/persistent/checkout/onepage/billing.phtml
<div class="field">
    <label for="billing:company"><?php echo $this->__('Company') ?></label>
    <div class="input-box">
        <input type="text" id="billing:company" name="billing[company]" value="<?php echo $this->escapeHtml($this->getAddress()->getCompany()) ?>" title="<?php echo $this->__('Company') ?>" class="input-text required-entry" />
    </div>
</div>

you can find the company input field around line 49 and add the class

class="input-text required-entry"

Let’s test it. Try to continue to the next step and notice the “This is a required field” message under the company field now. Company is now a required field (yeah yeah, I know I didn’t add the red star! that’s just styling…)Company is now a required field

But wait there’s more! There’s a whole list of ready to use validation rules to choose from… You can find the methods yourself by looking in js/prototype/validation.js starting around line 414

'validate-no-html-tags'         => 'HTML tags are not allowed'
'validate-select'               => 'Please select an option.'
'required-entry'                => 'This is a required field.'
'validate-number'               => 'Please enter a valid number in this field.'
'validate-number-range'         => 'The value is not within the specified range.'
'validate-digits'               => 'Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas.'
'validate-digits-range'         => 'The value is not within the specified range.'
'validate-alpha'                => 'Please use letters only (a-z or A-Z) in this field.'
'validate-code'                 => 'Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.'
'validate-alphanum'             => 'Please use only letters (a-z or A-Z) or numbers (0-9) only in this field. No spaces or other characters are allowed.'
'validate-alphanum-with-spaces' => 'Please use only letters (a-z or A-Z), numbers (0-9) or spaces only in this field.'
'validate-street'               => 'Please use only letters (a-z or A-Z) or numbers (0-9) or spaces and # only in this field.'
'validate-phoneStrict'          => 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.'
'validate-phoneLax'             => 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.'
'validate-fax'                  => 'Please enter a valid fax number. For example (123) 456-7890 or 123-456-7890.'
'validate-date'                 => 'Please enter a valid date.'
'validate-date-range'           => 'The From Date value should be less than or equal to the To Date value.'
'validate-email'                => 'Please enter a valid email address. For example johndoe@domain.com.'
'validate-emailSender'          => 'Please use only visible characters and spaces.'
'validate-password'             => 'Please enter 6 or more characters. Leading or trailing spaces will be ignored.'
'validate-admin-password'       => 'Please enter 7 or more characters. Password should contain both numeric and alphabetic characters.'
'validate-both-passwords'       => 'Please make sure your passwords match.'
'validate-url'                  => 'Please enter a valid URL. Protocol is required (http://, https:// or ftp://)'
'validate-clean-url'            => 'Please enter a valid URL. For example http://www.example.com or www.example.com'
'validate-identifier'           => 'Please enter a valid URL Key. For example &quot;example-page&quot;, &quot;example-page.html&quot; or &quot;anotherlevel/example-page&quot;.'
'validate-xml-identifier'       => 'Please enter a valid XML-identifier. For example something_1, block5, id-4.'
'validate-ssn'                  => 'Please enter a valid social security number. For example 123-45-6789.'
'validate-zip'                  => 'Please enter a valid zip code. For example 90602 or 90602-1234.'
'validate-zip-international'    => 'Please enter a valid zip code.'
'validate-date-au'              => 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.'
'validate-currency-dollar'      => 'Please enter a valid $ amount. For example $100.00.'
'validate-one-required'         => 'Please select one of the above options.'
'validate-one-required-by-name' => 'Please select one of the options.'
'validate-not-negative-number'  => 'Please enter a number 0 or greater in this field.'
'validate-zero-or-greater'      => 'Please enter a number 0 or greater in this field.'
'validate-greater-than-zero'    => 'Please enter a number greater than 0 in this field.'
'validate-state'                => 'Please select State/Province.'
'validate-new-password'         => 'Please enter 6 or more characters. Leading or trailing spaces will be ignored.'
'validate-cc-number'            => 'Please enter a valid credit card number.'
'validate-cc-type'              => 'Credit card number does not match credit card type.'
'validate-cc-type-select'       => 'Card type does not match credit card number.'
'validate-cc-exp'               => 'Incorrect credit card expiration date.'
'validate-cc-cvn'               => 'Please enter a valid credit card verification number.'
'validate-ajax'                 => ''
'validate-data'                 => 'Please use only letters (a-z or A-Z), numbers (0-9) or underscore(_) in this field, first character should be a letter.'
'validate-css-length'           => 'Please input a valid CSS-length. For example 100px or 77pt or 20em or .5ex or 50%.'
'validate-length'               => 'Text length does not satisfy specified text range.'
'validate-percents'             => 'Please enter a number lower than 100.'
'validate-cc-ukss'              => 'Please enter issue number or start date for switch/solo card type.'

Easy right? Yep, but wait that’s not all, what if you wanna validate based on some other set of conditions not in the list?

Example B

Sticking with our checkout example, let’s say we want to add a validation rule that prevents PO Box addresses in checkout. First, open up billing.phtml again and find the address fields (there are two of them starting around line 61). Next, add the class name we’re gonna use on the input fields.. we’ll call this one validate-for-pobox

/app/design/frontend/rwd/enterprise/template/persistent/checkout/onepage/billing.phtml
<?php $_streetValidationClass = $this->helper('customer/address')->getAttributeValidationClass('street'); ?>
        <li class="wide">
            <label for="billing:street1" class="required"><em>*</em><?php echo $this->__('Address') ?></label>
            <div class="input-box">
                <input type="text" title="<?php echo $this->__('Street Address') ?>" name="billing[street][]" id="billing:street1" value="<?php echo $this->escapeHtml($this->getAddress()->getStreet(1)) ?>" class="input-text validate-for-pobox <?php echo $_streetValidationClass ?>" />
            </div>
        </li>
<?php $_streetValidationClass = trim(str_replace('required-entry', '', $_streetValidationClass)); ?>
<?php for ($_i = 2, $_n = $this->helper('customer/address')->getStreetLines(); $_i <= $_n; $_i++): ?>
        <li class="wide">
            <label for="billing:street<?php echo $_i ?>"><?php echo $this->__('Street Address %s', $_i) ?></label>
            <div class="input-box">
                <input type="text" title="<?php echo $this->__('Street Address %s', $_i) ?>" name="billing[street][]" id="billing:street<?php echo $_i ?>" value="<?php echo $this->escapeHtml($this->getAddress()->getStreet($_i)) ?>" class="input-text validate-for-pobox <?php echo $_streetValidationClass ?>" />
            </div>
        </li>
<?php endfor; ?>

All we have to do now is add a new validation rule in JS for this class name, kinda like the ones in validation js. We’ll write ours right here in billing.phtml. Down on line 220… you’ll see

var billingForm = new VarienForm('co-billing-form');

remember that time, way back at the beginning of this post, when you read some stuff about passing the form id to VarienForm object?

below it, add

    Validation.add('validate-for-pobox','ERROR MESSAGE',function(field_value) {
        // setup a regex var for pretty much every possibility of PO box...
        var regex = /[P|p]*(OST|ost)*\.*\s*[O|o|0]*(ffice|FFICE)*\.*\s*[B|b][O|o|0][X|x]/;
        // if the field_value contains PO Box
        if(field_value.match(regex)){
            return false;
        }
        return true;
    });

Now try a test in checkout and behold
Screen_Shot_2014-11-04_at_15_42_14

What just happened?

 Validation.add('validate-for-pobox','ERROR MESSAGE',function(field_value) { amazing code here }); 

validate-for-pobox — the class name we want to use to kick off validation on input fields
ERROR MESSAGE — the error message , duh! (it’ll display below the field in red…)
field_value — the value the user types into the field.

That’s pretty much it. Time to validate stuff…

Posted By

HEI Team

Comments (2)

Alex posted

Thanks. It was helpful.

fayt posted

Thanks, really nice explanation.

Post a comment