The Silver Lining

Lessons & Learnings from a salesforce certified technical architect.

Salesforce Form Validation Enhanced

with 56 comments

I have a dream, and in this dream form-validation is not a chore. All the nasty work is done client-side, and we – the developers – control what an error message says and where it says it! Server-side validation?! Pah, I spit in it’s general direction (but only if no ladies are present). I don’t need or want client-server round-trips.. I want speed, I want beauty, I want control; and I think you do too.

Our end goal: A neat, realtime, client-side validation technique for VisualForce.

Using either inputFields, Apex exception handling and/or the ‘required’ attribute in VisualForce, we have a number of mechanisms to deal with form-validation, but if we’re honest with ourselves, they’re the ten-thousands-spoons when all we need is a knife. I know you’ve heard me singing it’s praise from the rooftops, but yet again, jQuery is here to save the day.

In preparation you may want to read this article on VisualForce and JavaScript.

Using a typical web registration form as an example, we’d typically expect our VisualForce to look something like this,

          <apex:pagemessages></apex:pagemessages>

                <apex:form id="commentForm">

                        <apex:outputlabel for="name">Name (required, at least 2 characters)</apex:outputlabel>
                        <apex:inputtext id="name" value="{!name}"></apex:inputtext>

                        <apex:outputlabel for="email">E-Mail (required)</apex:outputlabel>
                        <apex:inputtext id="email" value="{!email}"></apex:inputtext>

                        <apex:outputlabel for="url">URL (optional)</apex:outputlabel>
                        <apex:inputtext id="url" value="{!url}"></apex:inputtext>

                        <apex:outputlabel for="comment">Your comment (required)</apex:outputlabel>
                        <apex:inputtextarea id="comment" value="{!comment}"></apex:inputtextarea>

                        <apex:outputlabel for="pwd">Password</apex:outputlabel>
                        <apex:inputsecret id="pwd" value="{!pwd}"></apex:inputsecret>

                        <apex:outputlabel for="cpwd">Password</apex:outputlabel>
                        <apex:inputsecret id="cpwd" value="{!cpwd}"></apex:inputsecret>

                        <apex:commandbutton action="{!save}" value="Submit"></apex:commandbutton>

                </apex:form>

How would we usually add validation? Well to enforce some of the more common rules you’d need to add the ‘required’ attribute on the desired fields, and in addition to that you would still need to perform server side validation using Apex, which is slow, and takes a lot of monotonous effort.

Of course inputFields have quite a bit of neat baked-in validation, but what if we’re not working with SObject fields (or selectlists or we want more validation than just required or we want validation to happen in realtime or.. or.. or.. )?

So how do we “fix” this? Well I’m glad you asked, because it’s easier than you might think. Starting at the beginning we’ll need to include the base jQuery library in our page, as well as the jQuery Validate plugin,

    <apex:includescript value="{!$Resource.jquery}"></apex:includescript>
    <apex:includescript value="http://ajax.microsoft.com/ajax/jquery.validate/1.6/jquery.validate.min.js"></apex:includescript>

And then we can start with the real magic. In the document.ready() jQuery function we attach the validate event-handler to the form, and using the short, human-readable syntax, we attach rules – with their specific requirements – to each field,

$(document).ready(function() {
    
    $('[id$=commentForm]').validate();             
    
    $('[id$=name]').rules("add",{
        required: true,
        minlength: 5
    });     
   
    $('[id$=email]').rules("add",{
        required: true,
        email: true
    });      
   
    $('[id$=url]').rules("add",{
        url: true
    });
   
    $('[id$=comment]').rules("add",{
        required: true
    });
   
    $('[id$=pwd]').rules("add",{
        required: true,
        minlength: 5
    });
   
    $('[id$=cpwd]').rules("add",{
        required: true,
        minlength: 5,
        equalTo: '[id$=pwd]'
    });    

    /* Continued below */

The syntax is straight-forward, for each VisualForce element we’re ADDing a set of rules. For some we are dictating that they be required, for others we’re saying they must adhere to the recognised form of a URL or EMAIL ADDRESS. We even have the ability to easily say that the password- and password-confirmation fields must be the same. Not only that, but we can combine the rules to any degree we wish! I’ve only listed a few of the rule options here, there are many others such as NUMBER, TEXT, CREDIT CARD, DATE, NUMBER RANGES as well as the ability to write your own custom validations. Additionally you can customise the wording of the error message,

            /* Customised the messages */
            jQuery.validator.messages.required = "You better have entered a value.. or else!";
            jQuery.validator.messages.equalTo = "No silly, you're supposed to type the same set of characters AGAIN.";
        });

These messages can include images; be grouped together at the top of the page (or anywhere else) or appear independently. Messages are also displayed in AJAXy realtime without any client-server round-trips. This, ladies and gentlemen is the the mother of all validation libraries, and it is far too big for me to [re]document. The example I’ve given is enough to get you going and I invite, nay, I challenge you to dig into it’s depths. The full documentation can be found on the jQuery site, but I’d recommend taking a look at a few of the worked examples on the plugin-creator’s site, and checkout the above VisualForce code in action.

The full code is listed below (feel free to correct/optimise/twist/tweak/break in all manners imaginable).

<apex:page standardcontroller="Account" showHeader="false" standardStylesheets="false">
    
    <apex:includeScript value="{!$Resource.jquery}"/>
    <apex:includeScript value="http://ajax.microsoft.com/ajax/jquery.validate/1.6/jquery.validate.min.js"/>
    
    <script type="text/javascript"> 
        $(document).ready(function() {
             
            $('[id$=commentForm]').validate();             
             
            $('[id$=name]').rules("add",{
                required: true,
                minlength: 5
            });     
            
            $('[id$=email]').rules("add",{
                required: true,
                email: true
            });      
            
            $('[id$=url]').rules("add",{
                url: true
            });
            
            $('[id$=comment]').rules("add",{
                required: true
            });
            
            $('[id$=pwd]').rules("add",{
                required: true,
                minlength: 5
            });
            
            $('[id$=cpwd]').rules("add",{
                required: true,
                minlength: 5,
                equalTo: '[id$=pwd]'
            });      
            
            /* Customised the messages */
            jQuery.validator.messages.required = "You better have entered a value.. or else!"; 
            jQuery.validator.messages.equalTo = "No silly, you're supposed to type the same set of characters AGAIN.";                                                
        });
        
    </script>   
    
    <!-- Ignore my template -->
    <apex:composition template="Template">
        <apex:define name="title">
            <a href="http://thesilverlining-developer-edition.na7.force.com/jqueryvalidatedemo/">jQuery Forms Validation Demo</a>
        </apex:define>
        
        <apex:define name="blurb">
            <p>
                Fiddle with the form entering combinations of correct and incorrect values to see the validation rules in action. Hitting the sumbit button will also trigger form checking.
            </p>
        </apex:define>


        <apex:define name="content">    
            <apex:outputPanel layout="block" style="text-align:center; font-size:12px;padding: 4px">
                <apex:form id="commentForm" > 

                        <apex:outputlabel for="name">Name <span class="star">*</span></apex:outputlabel> 
                        <apex:inputtext id="name" value="{!account.name}"/>
                        <br/>
                        <apex:outputlabel for="email">E-Mail <span class="star">*</span></apex:outputlabel> 
                        <apex:inputtext id="email"  value="{!account.name}"/> 
                        <br/>
                        <apex:outputlabel for="url">URL (optional)</apex:outputlabel> 
                        <apex:inputtext id="url"  value="{!account.name}" /> 
                        <br/>
                        <apex:outputlabel for="comment">Your comment <span class="star">*</span></apex:outputlabel> 
                        <apex:inputtextarea id="comment" value="{!account.name}" style="width: 30%"/>
                        <br/>
                        <apex:outputLabel for="pwd">Password <span class="star">*</span></apex:outputLabel>
                        <apex:inputSecret id="pwd" value="{!account.name}"/>
                        <br/>
                        <apex:outputLabel for="cpwd">Confirm Password <span class="star">*</span></apex:outputLabel>
                        <apex:inputSecret id="cpwd" value="{!account.name}"/>                        
                        <br/>
                        <input type="submit" />
            
                </apex:form>
            
            </apex:outputPanel>
            
        </apex:define>
        
    </apex:composition>
     
</apex:page>

Written by Wes

March 2, 2010 at 11:44 am

56 Responses

Subscribe to comments with RSS.

  1. Falling in love with JQuery aren’t you? Well I have to admit it’s a neat and clear way of validating forms.
    Good post again!
    /MRG

    Morongroover

    March 2, 2010 at 11:56 am

  2. Nice post, Wes.

    Jill

    March 2, 2010 at 4:00 pm

  3. Awesome example. I’m gonna sit down tonight and bang out this code. Thanks, you are a peach.

    Jeff Douglas

    March 2, 2010 at 6:31 pm

  4. Great post as always and much love for jQuery.

    I’ve got so many jQuery + salesforce blog posts in the works it’s a little ridiculous…..ridiculously awesome.

    Jason

    March 2, 2010 at 10:09 pm

  5. Sweet! Need to play with JQuery asap.

    Michael Smith

    March 2, 2010 at 11:08 pm

  6. I can’t wait to jump on this bandwagon.

    Joel Dietz

    March 4, 2010 at 3:23 am

  7. I can’t believe. Is it really that simple?

    Rajesh

    March 9, 2010 at 5:01 pm

    • Indeed! jQuery is simple and powerful.

      Wes

      March 9, 2010 at 5:11 pm

  8. […] by Wes Nolte’s post on enhanced Visualforce form validation with JQuery, we have decided to implement JQuery validation in semi-automated […]

  9. Great Post!

    Osama

    March 11, 2010 at 6:53 am

  10. Very cool stuff!

    Although I would add that you should always do the server side validation as well since it’s easy for malicious users to by pass any javascript validation, but thats just a matter of using the declarative interface to write the same rules that are implemented in the javascript.

    Scott Morrison

    March 13, 2010 at 5:57 pm

    • Indeed! Very good advice.

      Wes

      March 13, 2010 at 6:01 pm

      • I’m confused. Isn’t protecting against malicious users a simple matter of appropriately escaping things before they go into query strings? If it is bad/fake data you are worried about, there is no way to protect against it that I know of.

        Jd

        March 13, 2010 at 6:06 pm

      • I am not sure that Scott necessarily meant someone trying to inject SOQL or something like that. It seems like his concern is with someone sidestepping the validation to put in any garbage data they want into a text field. You’d be duplicating your efforts to create client side and server side validation to guard against improperly formatted data.

        Alexis

        March 17, 2010 at 6:24 pm

      • In that case, I’m planning to develop a standard JQuery library for all standard fieldTypes in SFDC, to make the validation easier. Hopefully I’ll be able to integrate it w/ the form generation included in CMSForce.

        Jd

        March 17, 2010 at 10:22 pm

  11. Hi –

    Thanks for the providing neat and clear solution on the validation.

    I am trying this and having some road blocks. Can some one please address where the issue is?
    This is the one i am trying.

    I am receiving error: Static Resource JQuery not found
    and sometimes
    unexpected token: ” at line 0 column -1.

    Please advise.Thanks

    $(document).ready(function()
    {

    $(jq(f)).validate();

    $(jq(vendor_meet)).rules(“add”,{
    required: true
    });

    jQuery.validator.messages.required = “Please enter a value”;
    jQuery.validator.messages.equalTo = “You have to enter a value. Please!!!”;
    });

    var vendor_meet = “{!$Component.vendor_meet}”;

    Vendor (required)

    function jq(myid)
    {
    return ‘#’ + myid.replace(/(:|\.)/g,’\\\\$1′);
    }

    var f = “{!$Component.commentForm}”;

    renuami

    March 17, 2010 at 4:49 pm

    • Yes, you must create a static resource with the JQuery library.

      For example:

      there is a static resource called jquery that contains the Jquery library.

      Cheers.

      Pablo

      March 31, 2010 at 10:37 pm

  12. Wes,

    Really digging this jquery form validation functionality! However, I’m having issues getting it to work. I’ve combed through my code dozens of times and it appears to look correct per the sample code on this post. I’ve also checked my VF Id’s using Firebug and the problem doesn’t appear to lie there. But when I submit my form – voila! it submits without any validation.

    My page does reference other libraries like Mootools so I’m wondering if it has something to do with that. Anyone else have problems while using multiple js libraries on one page?

    Thanks!

    Clint

    April 17, 2010 at 4:45 pm

    • Hey Clint

      Other libraries can cause conflicts (it’s usually a namespace thing), Tehnrd has a good article detailing the fix, you can get it here: http://www.tehnrd.com/setting-up-jquery-with-salesforce-com/.

      Wes

      April 17, 2010 at 5:24 pm

      • Awesome! You’re the man. I just had to add the following:

        var j$=jQuery.noConflict();

        then change my $ to j$.

        Working like a charm. Thanks to you and Jason (@tehnerd)

        Clint

        April 18, 2010 at 2:07 am

  13. I’m late to the party, but this is exactly what I was looking for. Thanks!

    Christian

    August 13, 2010 at 4:37 pm

  14. There seems to be an error in the following portion. Spent a lot of time tracking this one down. I feel like an idiot.

    return ‘#’ + myid.replace(/(:|\.)/g,’\\$1′);

    should be

    return ‘#’ + myid.replace(/(:|\.)/g,’\\\$1′);

    It is correct in your actual example, but not in the above text.

    jp

    January 7, 2011 at 7:24 am

    • Thanks for that, WordPress messes around with my markup, especially in this example because of all the JS :\

      On a side note, I’ve found that on some of the servers you only need ‘\\’ while on others you’ll nee ‘\\\’. It’s a lovely inconsistency, but if you know what to look for when problems occurs it’s quick to find.

      Wes

      January 7, 2011 at 11:48 am

  15. Only wanna tell that this is invaluable , Thanks for taking your time to write this.

    Living On A Dime

    February 23, 2011 at 6:49 pm

  16. FROM: http://www.salesforce.com/us/developer/docs/pages/Content/pages_variables_global.htm
    If your component is nested, you must declare the entire component tree.
    For example:
    “{!$Component.theBlock.theSection.theSectionItem.text}”

    colemab

    June 21, 2011 at 8:15 pm

    • This is true but it’s not the only way and if fact it’s quite brittle as discussed here: https://th3silverlining.com/2009/06/17/visualforce-component-ids-javascript/.

      Wes

      June 21, 2011 at 8:36 pm

      • First off, thanks for the write up, time and effort.

        Yea, the down side to the document.getElementById method is that it has to be at the same level as the object in question. This leads to having to maintain script sections at each level to be ‘dynamic’ vs. having to maintain the full component tree.

        I am trying to get this to work and my first problem was that my ID’s were not pulling back. Now they are pulling correctly and so I thought I would share the ‘fix’ for that since your example doesn’t have as many levels as mine.
        It still doesn’t appear to be working in my sandbox though.

        colemab

        June 21, 2011 at 9:12 pm

    • Correct, neither method is perfect unfortunately, c’est la vie. Some people prefer one method to another. I know that my friend Jason (tehnrd) does not dig my approach.

      Recently I’ve been thinking that we should just wildcard our jQuery selectors, you can give this a bash as shown here:http://james.padolsey.com/javascript/regex-selector-for-jquery/

      If we were to use this approach we could give our visualforce element of id=”el-id” and then select it in jQuery using something like $(‘*el-id’).

      Good luck.

      Wes

      June 21, 2011 at 9:34 pm

  17. Please, do not approve my previous post. but, approve this one:

    I get no validation messages. Not sure why?

    $(document).ready(function() {
    /* Note: The jq() function is explained @ http://wp.me/pxPpB-8B */
    $(jq(f)).validate();

    $(jq(name)).rules(“add”,{
    required: true,
    minlength: 2
    });

    $(jq(email)).rules(“add”,{
    required: true,
    email: true
    });

    $(jq(url)).rules(“add”,{
    url: true
    });

    $(jq(comment)).rules(“add”,{
    required: true
    });

    $(jq(password)).rules(“add”,{
    required: true,
    minlength: 5
    });

    $(jq(cpassword)).rules(“add”,{
    required: true,
    minlength: 5,
    equalTo: jq(password)
    });

    /* Customised the messages */
    jQuery.validator.messages.required = “You better have entered a value.. or else!”;
    jQuery.validator.messages.equalTo = “No silly, you’re supposed to type the same set of characters AGAIN.”;
    });

    var name = “{!$Component.name}”;

    Name

    ATS Journal Type

    Active

    Refundable

    Refund pro-Rate

    Disallow Person Account Purchase

    Disallow Standard Account Purchase

    Allow Line Description Input

    Staff Only

    Non-Standard Product

    Purchasable

    Opt Out Allow

    Allow Multiple Quantity Purchase

    Allow Price Adjustments

    Allow Price Write-Off

    Require Approval

    Journal Issue #

    Journal Volume

    U.S. Price

    International Price

    Journal Issue Date

    Purchasable Expiration Date

    Quantity Ordered

    Quantity Limitation

    Product Description

    Allow Nation Group

    Product Group

    Product Family

    Dynamics GP Batch ID Prefix

    Credited General Ledger Account

    function jq(myid){
    return ‘#’ + myid.replace(/(:|\.)/g,’\\$1′);
    }

    var f = “{!$Component.atsJournalEntryForm}”;

    Mike Clayton

    August 15, 2011 at 9:49 pm

    • Looks like your markup has been stripped out. I’m going to delete your comment but if you could post in the SFDC developer forums and post a link here I’ll take a look.

      Wes

      August 16, 2011 at 11:23 am

  18. Hi
    First of all thanks for sharing the great piece of work .!
    I am trying to use this in a visual force page. I am getting an error at the validate() function and it says “Unspecified”.
    I have included the static resources as mentioned by your blog.
    Notifiably, I have other java script and jquery methods are working fine.

    I do not understand why it was not working for me..

    Please help me

    Thanks
    Sai.

    Sai

    October 31, 2011 at 5:26 am

  19. Has anyone tried this with apex:inputField’s ? How do we handle the lookup icon/image when a jquery validation messages is added to these fields?

    The jQuery validation message renders after the form input field. In the HTML layout structure, the validation message is inserted between the the text field and the lookup icon. For me, this has become a CSS mess as I have the lookup icon moving around, or being placed behind the validate message, or my validate messages have issues if they need to line wrap. Everything regarding jQuery validation was fine until I came across forms that use lookup (inputField) in them. jQuery validate continues to work, but the presentation has become somewhat tricky.

    Hopefully someone who is using this method with inputFields in their forms has some ideas.Thanks.

    David

    November 21, 2011 at 6:59 pm

  20. i get no validation messages.. i already uploaded the static resources, copied your code, and still couldn’t make it work.. please help..

    Cherr

    December 14, 2011 at 7:36 am

  21. What i’d like to know is if there is a way to use something like Jquery Tools (with a much nicer validation graphics) – i can’t seem to figure out how to add the required=”required” attribute to an necessary to trigger validation on that plugin…

    James

    February 11, 2012 at 11:04 am

    • to an *inputfield* necessary… stripped out my tags

      James

      February 11, 2012 at 11:05 am

    • I’m sorry I don’t know what you’re asking. This post details how to use validation and it seems that’s what you’re asking?

      Wes

      February 12, 2012 at 3:12 pm

      • I think u can just use styleclass=”required” instead

        Jd

        February 12, 2012 at 3:26 pm

    • I’ve simplified the code significantly, have another read through 🙂

      Wes

      February 12, 2012 at 3:43 pm

  22. Where does the save() method get called?

    manattweb

    March 30, 2012 at 9:52 pm

    • It’s called by the commandbutton.

      Wes

      April 1, 2012 at 6:39 pm

      • In your “full” code block, I don’t see a commandbutton. It looks like you substituted it with a standard submit button.

        manattweb

        April 1, 2012 at 6:55 pm

      • That is true. It is shown in the code within the post although I can see how that might be confusing.

        Wes

        April 2, 2012 at 9:14 am

  23. We are using tabpanel to create a multi tab form. we have the form and tabs all worked out with next command buttons on each tab and submit on last tab. How can we get a “next tab” commandbutton to fire the validation on the fields if it is not a submit button? any ideas?

    we will be using validations ignore function to avoid validating other tabs fiels, so that is not an issue, just how to fire the validation with the “next” commandbutton

    BK

    April 2, 2012 at 8:46 am

    • Got this to work by adding submit event to onclick.

      BK

      May 22, 2012 at 7:11 pm

  24. This technique looks like it will save a lot of trouble – if I can get it to work for me. I’m currently getting a “element is undefined” (according to Firefox) error on the jquery validate script. I’m current loading the jquery code via these lines:

    I’m using jquery 1.3.2 and the jquery validate plugin 1.6 (same as in this example).

    Any ideas on what I’m doing wrong would be welcome.

    Is the following page structure critical to this technique?

    My form isn’t wrapped by a define or an output panel.

    Bruce Perry

    April 4, 2012 at 7:37 pm

  25. Has anyone gotten jquery validation to work with apex:selectRadio or checkbox?

    BK

    May 22, 2012 at 7:08 pm

  26. Hey! Thank you for taking the time to write this as well as address a few people’s questions/comments.

    I too am having trouble getting this to work and posted a follow up question to Bruce Perry’s post: http://boards.developerforce.com/t5/Visualforce-Development/Getting-JQuery-validation-working-in-Saleforce/m-p/421625/highlight/false#M48631

    I could really use someone’s help on this as I am not at all a js/jquery jedi master.

    Eugene

    August 10, 2012 at 7:29 pm

  27. […] and that a form field is not blank.  Here is a good article with examples <a href=”https://th3silverlining.com/2010/03/02/visualforce-form-validation-enhanced/”>at the silver […]

  28. Hi,

    This is a great article. Is the template you used available for reference as well?

    Thanks!

    Todd

    May 13, 2013 at 3:58 pm


Leave a reply to Wes Cancel reply