Fixing xforms-refresh

There is a bit of a problem with the xforms-refresh event: 
http://www.w3.org/TR/2006/REC-xforms-20060314/slice4.html#evt-refresh

The following is the smallest code that could break, depending on the 
order of events.  XForms defines no order for events, so this code may 
work on some implementations.  However, it is very easy to expand it to 
code that should break on all implementations.

<model>
   <instance>
      <data>
         <a>1</a>
      </data>
   </instance>
   <bind nodeset="a" constraint=". &lt; 10"/>
</model>

<input ref="a">
   <label>A</label>
   <setvalue ev:event="xforms-value-changed" ref=".[. >= 10]" value="1"/>
</input>

The above input will detect any value change on the node to which it is 
bound, and set the value back to one if the node ever becomes greater than 
or equal to 10.

The model also contains a simple constraint to enforce the same upper 
bound on the data.

So, let the user enter 10, which behaves like a setvalue action, which 
sets the node to 10, then does recalculate, revalidate, refresh.

1) Since the node value changed to 10, the xforms-refresh must dispatch 
both xforms-value-changed and xforms-invalid.  Assume that is the order.

2) So, the xforms-value-changed is dispatched.  This causes the setvalue 
action to run, which sets the node value back to 1, followed by 
recalculate, revalidate, refresh.

3) Since the node value changed to 1, the xforms-refresh must dispatch 
both xforms-value-changed and xforms-valid.  Assume that is the order.

4) Now we return from the dispatch of the xforms-value-changed in #1, and 
proceed to dispatch xforms-invalid.

The problem with #4 is that the last event dispatched to the control is 
xforms-invalid even though the data in the control is currently valid. 
Thus, bullet point 5 of xforms-refresh default processing is not achieved 
with a literal reading of bullet point 4.

There are two ways to fix the problem:

1) Immediately before emitting each notification, we have to check again 
whether the main condition for its dispatch holds.  So, for an 
xforms-invalid, if the bound node is valid at the moment of dispatch, then 
skip the dispatch.  I believe this is the best fix because it most closely 
matches what the form author is trying to do.  If there is an action that 
corrects a problem, then the author does not want to hear about the 
invalidity because the problem was corrected.  However, because we don't 
guarantee event order, it's not a guarantee we can end up making to the 
author.  However, it remains true that we would achieve bullet 5, and we 
could also consider dispatching all value changed events before the other 
events in the future.

2) We could modify recalculate and revalidate so that they do not mark for 
dispatch the actual notification events, but rather they *should* be 
marking event pairs for dispatch.  So, for example, revalidate should mark 
the valid/invalid pair for dispatch.  This would allow xforms-refresh to 
decide at the moment of dispatch whether to emit an xforms-valid or 
xforms-invalid based on the validity of the bound node at the moment 
before dispatch.

Best regards,
John M. Boyer, Ph.D.
Senior Product Architect/Research Scientist
Co-Chair, W3C XForms Working Group
Workplace, Portal and Collaboration Software
IBM Victoria Software Lab
E-Mail: boyerj@ca.ibm.com  http://www.ibm.com/software/

Blog: http://www.ibm.com/developerworks/blogs/page/JohnBoyer

Received on Friday, 8 September 2006 20:33:41 UTC