ShowTable of Contents
Row by row validation with a single XForms bind
This sample demonstrates how XPath can be used in an XForms constraint bind to mark a single field in a row as invalid. This can be accomplished with a single bind and a separate data element can be used to control which row is evaluated for the validation. This could be useful to notify the user of errors in a table that call webservices, for example.
The approach that's demonstrated in this form utilizes the "preceding-sibling" XPath axis. If you've never used or heard of XPath axes, you might be interested in looking them up on google, there are plenty of tutorials and explanations out there. Basically they allow you to select multiple XML elements based on their position relative to the current context node. For example, you can use axes to select preceding/following siblings (beneath the same parent as the context node), or preceding/following nodes (to select nodes before/after the context node across the whole document).
In order to understand this example, you first need to understand the constraint model item property (MIP) and how it works in an XForms bind. The key concept here is that the target of the bind is defined by the bind's nodeset property, and the constraint may or may not actually be concerned with that data. For example, it's perfectly legal to have a constraint bind which causes a "last name" field to become invalid when the user enters an invalid phone number in the phone number field (although not very user friendly, maybe). Of course, in most cases, the target nodeset of the bind is concerned with the same data that is being validated, but it's important to understand that the constraint MIP is purely a boolean test of an XPath to decide whether the nodeset in question is valid or not.
Let's get down to it. The bind that validates the rows in this table looks like this:
constraint="count(../preceding-sibling::*)+1 != instance('INSTANCE')/currentRow or instance('INSTANCE')/validation != 'e'"
The nodeset selects all the col1 elements (in all rows). This is important, because it means that all col1 elements are being validated at once. This means that with a bit of XPath logic operations in the constraint, we can ignore all but one row. In the constraint, there are two parts to the XPath, separated by a logical "or". The left side is true whenever the row that is currently evaluated (keep in mind that the bind is evaluated separately for each element in the nodeset) is not in the same position as indicated in the <
element. The count and preceding-sibling statement simply returns the row number for the current <
element. On the right side of the "or" is our validation. This a trivial example of some validation, in this case checking if the <
element consists of the letter 'e', you can replace this whatever you like.
Basically the validation on the right side is irrelevant if the bind is not looking at the "right" row, as selected by the <