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.

15 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
  10. Hi Bob, big fan here.

    Question.
    On your field level error example. Did you still have Apex:pageMessages on that page?

    I'm hoping to have generic errors show up in PagesMessages, but field level show up next to the field. Is that possible?

    ReplyDelete
  11. Hi Bob, you are an SFDC Hero :)

    One quick thing I am using this in one of my visualforce page in portal I am getting error just below the field but its in black color how can I get it with red color ? any idea

    ReplyDelete
  12. Hi Bob,
    I am trying to find a solution to this situation where i have a required field in the vf page and thus i see the red bar already and then I am also adding the custom validations. but my vf always throws the required field error first and only when the field has value, it shows the custom error message. While i want the custom and the standard error messages to be displayed all together.

    ReplyDelete