Friday, 22 April 2011

Field Level Error Messages with Visualforce - Part 1

A question came up on the Visualforce discussion board this week asking how to display validation error messages for particular fields on a Visualforce page.

For simple "field required" rules, there's nothing to be done as long as you are using <apex:inputField> components - the field will be decorated with a red bar and an attempt to save a record without the field populated presents a nice error message beneath the field, as shown below:


However, if a validation rule is added - in this case one of email or phone must be defined - you get redirected to a page similar to the following:


Not the greatest user experience in the world.  Clearly handling this via validation rules alone isn't going to work, so the next option that presents itself is to carry out the validation in the controller and send an error message back to the page.  Looking in the Visualforce docs, there is an <apex:pageMessages> component that can do exactly this, we just need to traverse the contacts and add the errors to the page as follows:

Boolean error=false;
Integer idx=1;
for (Contact cand : contacts)
{
 if ( (null==cand.Email || cand.Email.length()==0) &&
      (null==cand.Phone || cand.Phone.length()==0) )
 {
  error=true;
  ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Line ' + idx + ' - one of email or phone must be defined'));
 }
 idx++;
}

The resulting page is shown below:


Looking better, but still not the nicest page in the world.    What we really want is an error tied to the field itself, much like the required fields.  The secret here is to use the addError method available to sObject fields.  In this case, I've traversed the list of contacts and where both the email and phone are blank, added an error to each of the email and phone field detailing the error:

Boolean error=false;
Integer idx=1;
for (Contact cand : contacts)
{
 if ( (null==cand.Email || cand.Email.length()==0) &&
      (null==cand.Phone || cand.Phone.length()==0) )
 {
  error=true;
  cand.email.addError('Either email or phone must be defined');
  cand.phone.addError('Either email or phone must be defined');
 }
 idx++;
}

This results in exactly the behaviour I am looking for, and even better I don't have to make any changes the page, as its standard Visualforce that displays the error:


In part 2, we'll look at how to replicate this when the inputs aren't tied to an sobject field, for example if they come from a wrapper class.

12 comments:

  1. Good stuff! Thanks for sharing.

    ReplyDelete
  2. nice..thanks for sharing..

    ReplyDelete
  3. Great stuff.....just was looking out if we can try this out with date field..to check if date is entered correctly and no integer value is inserted.

    ReplyDelete
  4. Great guide very helpful.
    ..But does anyone know how to get this working using dynamic field references?
    like e.g. obj.get('customfield1').addError('error')

    ReplyDelete
  5. Before the user clicks submit/save, how do you get the fields to have the required indicator?

    ReplyDelete
  6. How to bind this with VF page field?

    ReplyDelete
    Replies
    1. I'm not sure I understand the question - this is bound to a field on the VF page. You add the error to the field and the Visualforce page changes accordingly. Can you provide some more detail?

      Delete
  7. Hi Bob, thanks for sharing.

    I want to use the already existing validation error messages which are coming from standard page.
    How can I make it, can you give me an idea instead of creating manual error messages?

    ReplyDelete
    Replies
    1. Unfortunately that leads to ugly error messages at the top of the page. This blog post was my findings after working around it.

      Delete
  8. Hi Bob,
    How do we achieve this for a custom picklist field whose values come from the controller. There are no validations rules for the entire object but the field is mandatory. I am not sure where to add the error message in the VF page/Controller class so that it displays as a standard error message ib the vf page.

    ReplyDelete
  9. Hi Bob
    I have a standard Validation error that says 'XYZ' is there anyway I can replace only the error message to say 'ABC' instead of showing 'XYZ'?

    ReplyDelete