Using jQuery to Validate User Input

This week on Twitter, @lesteb posted a question about the best way to validate if a user had checked one of two checkboxes on a Visualforce page. We went back and forth for a while about his requirements. Since Salesforce doesn’t have radio buttons and it is impossible to make a checkbox field required, we needed some other way to make sure his requirements were met. I had a couple of ideas.

My first thought was to use Validation Rules – this is a great button click feature of Salesforce and, as Nick Hamm so eloquently pointed out recently on his blog, we should try to use configuration first and code second. In this case Bryan couldn’t use validation rules because he only wanted it to validate on one page and wanted to have more control of the error message. Our next option to look at was putting in some logic in the controller extension save method. Again, Bryan ruled this out because he wanted more control over the error message.

So, I then suggested using Javascript to do some validation with help from jQuery. In Visualforce, we can use onClick to run some JavaScript before the Apex method assigned to the button is executed. In the example below, the beforeSave() function is called first and only if that function returns true will it go to the Apex method mySave.

<apex:commandbutton value="Save" id="saveBtn" action="{!mysave}" onClick="if(!beforeSave()) return false;"/>

The JavaScript function beforeSave is below. It uses jQuery to check the values of the the two checkboxes. At least one must be checked for the function to return true. If neither one is checked, it opens a jQuery UI dialog box telling the user to check a box. I’ll get into that in a minute.

function beforeSave() {
      if (!j$('[id$=checkbox1]').attr('checked') && !j$('[id$=checkbox2]').attr('checked')) {
        j$( "#dialog-message" ).dialog('open');
        return false;
      } else
        return true;

Now for the dialog box. First we need a div on the page that will be used for the message:

<div id="dialog-message" title="Info Needed">
        <span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 50px 0;"></span>
        You should check a box!

Once we have the div, we need to turn it into a jQuery UI Dialog. Here’s the way to do that:

j$(document).ready(function() {
        autoOpen: false,
        modal: true,
        buttons: {
          Ok: function() {
            j$( this ).dialog( "close" );

Bryan had one more requirement. Only one of the two checkboxes could be checked. I turned to a little more JavaScript to make this work. Here’s the visualforce markup where I added an onClick call to a JavaScript function to the input field.

<apex:inputField value="{!account.Checkbox1__c}" id="checkbox1" onClick="deselectOther(this);"/>

The JavaScript function to deselect one checkbox when the other gets checked is pretty simple. It gets the element clicked passed in, compares the id of that element and then use jQuery to find and uncheck the other one.

function deselectOther(e) {
      if ($/))
        j$('[id$=checkbox2]').attr('checked', false);
      if ($/))
        j$('[id$=checkbox1]').attr('checked', false);

Bryan did a nice little demo video of his nearly finished page. Note that this video was done before the final trick of deselecting one checkbox when the other was selected. He was handling this case with an error message.

I’ve created an unmanaged package that you can install into your org to see the entire sample code. It doesn’t match Bryan’s video entirely as he did a bunch of other messages and validations, but I hope it points you in the right direction. As always, I’d love to hear thoughts on how I could improve this, or maybe you have a completely different way to do it!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s