Committed fix to 4.0 trunk at revision 39907 and to 3.3. EE maintenance branch at revision 39908. The fix consists in adding an input reverting functionality to the cancel button of ace:rowEditor.
There was no real bug here. The 'x' button in ace:rowEditor wasn't a button for reverting the submitted values when editting a row. It's function was simply to cancel the row editting, which was accomplished by not executing any inputs in the request sent to the server when pressed. In fact, if you hover over that button, you'll see the tooltip reading 'Cancel Editing' and not 'Revert Editing', as specified by it's 'title' attribute.
However, if the values were already submitted by pressing the checkmark button, the cancel button didn't have the power of cancelling (reverting) what had been already submitted. Every input component is independent and goes through its own internal validation process, and this cancel button wasn't able to magically affect the internal state of all the input components in the row by simply cancelling the request, until now. That's a reason why we have the 'toggleOnInvalidEdit' attribute--to prevent exiting edit mode when there's a validation error, in order to give the user a chance to correct it.
Moreover, the normal behaviour of JSF input components is to render the 'submittedValue' (i.e. the invalid one) when validation fails. So, the invalid value wasn't supposed to be removed by simply hiding the input components when cancelling the row editing, since their 'rendered' attributes are not actually set to false, but they are simply skipped from rendering when not in edit mode.
Input reverting functionality was added to the decode() method of ace:rowEditor. The code retrieves all "input" facets from ace:cellEditor's in the row and goes through all EditableValueHolder instances and clears their submitted values and sets their valid flags to true. This causes the original, valid value to show when entering edit mode again after having cancelling the editing previously. This also allows other rows to be edited and submitted sucessfully, after reverting an invalid value. However, it's not possible to remove the FacesMessage associated with the initial failed validation. JSF simply doesn't provide a way to do that. The only way to remove it is to submit (and execute) again the input component that originally failed validation (now with a valid/original value).
An alternative, more practical solution that I found before implementing the fix above involves creating a special button at the app code level to revert the values of a row and submit them. It uses Javascript to locate each input component and reset its value to the original value used to render it. With this approach, the FacesMessage is also removed, since the inputs are submitted and executed, with their original values. For the showcase example, this approach would look like this and would be added to the last column, where ace:rowEditor is.
<ace:cellEditor><!-- only show button in edit mode -->
<f:facet name="output"><!-- cannot be empty -->
<h:panelGroup />
</f:facet>
<f:facet name="input">
<h:commandButton value="Revert values" onclick="
ice.ace.jq(this).closest('tr').find('input[id$=\'nameInput\']').val('#{car.name}');
ice.ace.jq(this).closest('tr').find('input[id$=\'chassisInput\']').val('#{car.chassis}');
ice.ace.jq(this).closest('tr').find('input[id$=\'weightInput\']').val('#{car.weight}');" />
</f:facet>
</ace:cellEditor>
Committed fix to 4.0 trunk at revision 39907 and to 3.3. EE maintenance branch at revision 39908. The fix consists in adding an input reverting functionality to the cancel button of ace:rowEditor.
There was no real bug here. The 'x' button in ace:rowEditor wasn't a button for reverting the submitted values when editting a row. It's function was simply to cancel the row editting, which was accomplished by not executing any inputs in the request sent to the server when pressed. In fact, if you hover over that button, you'll see the tooltip reading 'Cancel Editing' and not 'Revert Editing', as specified by it's 'title' attribute.
However, if the values were already submitted by pressing the checkmark button, the cancel button didn't have the power of cancelling (reverting) what had been already submitted. Every input component is independent and goes through its own internal validation process, and this cancel button wasn't able to magically affect the internal state of all the input components in the row by simply cancelling the request, until now. That's a reason why we have the 'toggleOnInvalidEdit' attribute--to prevent exiting edit mode when there's a validation error, in order to give the user a chance to correct it.
Moreover, the normal behaviour of JSF input components is to render the 'submittedValue' (i.e. the invalid one) when validation fails. So, the invalid value wasn't supposed to be removed by simply hiding the input components when cancelling the row editing, since their 'rendered' attributes are not actually set to false, but they are simply skipped from rendering when not in edit mode.
Input reverting functionality was added to the decode() method of ace:rowEditor. The code retrieves all "input" facets from ace:cellEditor's in the row and goes through all EditableValueHolder instances and clears their submitted values and sets their valid flags to true. This causes the original, valid value to show when entering edit mode again after having cancelling the editing previously. This also allows other rows to be edited and submitted sucessfully, after reverting an invalid value. However, it's not possible to remove the FacesMessage associated with the initial failed validation. JSF simply doesn't provide a way to do that. The only way to remove it is to submit (and execute) again the input component that originally failed validation (now with a valid/original value).
An alternative, more practical solution that I found before implementing the fix above involves creating a special button at the app code level to revert the values of a row and submit them. It uses Javascript to locate each input component and reset its value to the original value used to render it. With this approach, the FacesMessage is also removed, since the inputs are submitted and executed, with their original values. For the showcase example, this approach would look like this and would be added to the last column, where ace:rowEditor is.