execChangedValue not firing if an invalid value is reverted back to the previous value [message #1220946] |
Mon, 16 December 2013 10:09 |
Urs Beeli Messages: 573 Registered: October 2012 Location: Bern, Switzerland |
Senior Member |
|
|
Background for this bug
In our application we have forms where there are both validation rules for each single field (covered in their execValidateValue() methods) and some multi-field-validation rules. Those rules are checked in one common method validateFields() which is called from each fields execValueChanged() method.
Let's assume the following case to illustrate our problem
- We have two fields: An integer field and a checkbox
- The integer field has an execValidateValue() method which validates the raw value of the IntField (say any value > 4000 throws a VetoException)
- In the execChangedValue() methods of both fields we call validateFields() to do the multi-field validations (say if the checkbox is set and the int field contains an even value, its error status is set; if the checkbox is not set and the int field contains an odd value, its error status is set).
The Problem
- Let's assume that the checkbox is set
- The user now enters a new value into the int field: 444
- execValidateValue() on the IntField accepts the value (it's below 4000)
- execChangedValue() calls our validation method validateFields() which detects an even value and sets the error status on the IntField.
The IntField now shows an error status
- Now, the user enters a new value into the int field: 4444
execValidateValue() on the IntField throws a VetoException, the IntField now shows the new error status, execChangedValue() is never called
- Now, the user corrects his mistake, restoring the old value: 444
- execValidateValue() on the IntField accepts the value (it's below 4000)
As AbstractValueField.setValue() contains the following lines:
if (getErrorStatus() instanceof ValidationFailedStatus) {
clearErrorStatus();
}
and
if (getErrorStatus() instanceof ParsingFailedStatus) {
clearErrorStatus();
}
These lines clear the error status of the IntField. Our initial condition still applies: The checkbox is set and an even value is in the IntField, our validateFields() method would set the error status again. However, execChangedValue() is never called on the IntField, as the oldValue and the newValue are both 444 (the vetoed value 4444 was never propagated far enough).
Is there any way of setting up a multi-field-validation routine that will work correctly in the described case?
|
|
|
|
|
|
|
|
Re: execChangedValue not firing if an invalid value is reverted back to the previous value [message #1229002 is a reply to message #1221984] |
Wed, 08 January 2014 14:22 |
Ken Lee Messages: 97 Registered: March 2012 |
Member |
|
|
Jeremie Bresson wrote on Thu, 19 December 2013 03:05In my opinion, you cannot mix error handling in execValidateValue and execChangedValue.
I suppose that Jérémie is right. The Javadoc of execValidateValue says:
/**
* WHILE (not after) a new value is validating (that means the new value has
* not yet been set), this methode is called.<br>
* Check the new proposed value and either make it valid by returning this or
* another valid value or reject by throwing a {@link VetoException}, it will
* then appear red in the gui.
*
* @return the validated value or throws an exception
*/
whereas execChangedValue says:
/**
* AFTER a new valid value was stored (that means the value is valid), this
* method is called and can be used to broadcast this change to other fields
* by for example calling {@link IValueField#setValue(Object)} on another
* field...
This means that in your case the value is not valid and therefore the method execChangedValue will not get fired.
Urs Beeli wrote on Mon, 06 January 2014 02:05Jeremie, do you see any way to work around that limitation? How would you propose to do "multi field validation"?
In one of our Scout project, we also have to do multiple field validation. Similar to your approach we have a validator that is implemented as a service however. The service is located in the shared package so that it could used in the client without having to call a server service.
In the execChangedValue method the current values of the form is exported into a formdata and then passed to the validator service.
After validation, the validated formdata is imported again. Be aware to set the flag valueChangeTriggersEnabled to false when calling the method importFormData. Otherwise, the validated values could trigger execChangedValue again
With this approach, we don't use the execValidateValue method at all.
|
|
|
|
Powered by
FUDForum. Page generated in 0.04650 seconds