XFA 3.0: Validation State Change Event

The field, exclGroup and subform elements have a new event: validationState.  The primary use of this event is to change the appearance of fields as they become valid or invalid.

Just for review — there are three ways in which objects can be considered invalid:

  1. A mandatory field/exclusion group that does not have a value
  2. A field with a value that cannot be formatted with its validation picture format
  3. A field/subform/exclusion group whose validation script returns "false"

Rules controlling the validationState Event

The validationState event fires under the following conditions:

  • Immediately following the initialize event — allowing the form author to control the initial appearance of the object
  • When the field/subform/exclusion group transitions between a valid and invalid state (or vice versa).
  • When the reason for the invalid state changes e.g. a field is in an invalid state because it is not filled in (missing mandatory).  The user then fills in a value that violates the validation picture clause.  In this case the field goes from one invalid state to a different invalid state and the event will fire.
  • The form session begins tracking mandatory fields

The last point needs a bit more explanation.  When a field is marked as mandatory, it starts the form session in a valid state — even though it does not have a value.  The reason is that we don’t want users notified about a whole bunch of invalid empty fields as soon as they open a blank form.  There are 3 things that will put a missing mandatory field into an invalid state:

  1. A populated mandatory field gets emptied
  2. A call to execValidate() on the field or one of its ancestors
  3. A submit action (which is really the same as an execValidate())

When any one of these three operations happen, the validationState event will fire for any unpopulated mandatory fields.

To be on the safe side, script associated with the validationState event should be robust enough to allow the event to fire multiple times — even if the validation state hasn’t actually changed.

The new errorText property

So the validationState event has fired… how does the script author know whether the field is now in a valid or invalid state?  Authors can check the new property on field/subform/exclusion group: errorText.  When a field is in a valid state, this property will return an empty string.  When in an invalid state, it will return the user-defined message for that error. 

Objects may have 3 different user-defined messages — one for each kind of validation failure.  These messages are represented in the scripting model as:

field.validate.message.scriptTest.value
field.validate.message.formatTest.value
field.validate.message.nullTest.value

or via their shortcut properties:

field.validationMessage
field.formatMessage
field.mandatoryMessage

The errorText property will be populated with the message from the associated validation failure.  If the user has not defined a message, a default message is provided ("Validation failed.").

Turning off Acrobat/Reader Field Highlighting

If you are using the validationState event to change the appearance of fields, the automatic field highlighting of Acrobat/Reader can get in the way.  Fortunately, it can be turned off.  This script (placed on a form:ready event) will do the trick:

    if (xfa.host.name == "Acrobat")
       app.runtimeHighlight = false;

Example

This example will hide the border on valid fields and for invalid fields will colour the border red.  Note that the example places the script on a subform and uses event propagation to cause it to apply to all nested objects.

<subform>
  <event activity="validationState" listen="refAndDescendents">
    <script>
      if (HasValue($event.target.errorText)) then
        $event.target.edge.presence = "hidden";
      else
        $event.target.edge.presence = "visible";
        $event.target.borderColor = "255,0,0"
      endif
    </script>
  </event>
</subform>