Issue Details (XML | Word | Printable)

Key: JAVASERVERFACES_SPEC_PUBLIC-1060
Type: Improvement Improvement
Status: Closed Closed
Resolution: Duplicate
Priority: Major Major
Assignee: Ed Burns
Reporter: balusc
Votes: 12
Watchers: 12
Operations

If you were logged in you would be able to see more operations.
javaserverfaces-spec-public

Reset EditableValueHolders which are not covered by ajax execute before ajax render

Created: 09/Dec/11 08:31 PM   Updated: 06/Nov/12 04:17 AM   Resolved: 06/Nov/12 04:17 AM
Component/s: None
Affects Version/s: 2.0
Fix Version/s: None

Time Tracking:
Not Specified

Issue Links:
Duplicate
 
Related
 

Tags:
Participants: arjan tijms, balusc, Ed Burns, kito75, ova2 and wrschneider99


 Description  « Hide

Background:

Problems:

  • When an EditableValueHolder component is in an invalid state or has only its local value set, and an ajax request needs to render the component while it is not included in the execute, then the original/updated model value won't be displayed, but instead the originally submitted value or the local value will be displayed. This is not intuitive.

Enhancement request:

  • When JSF needs to render an EditableValueHolder component by an ajax request, and that EditableValueHolder component is not included in the execute of the ajax request, then JSF should invoke EditableValueHolder#resetValue() on it in order to display the proper model value.


wrschneider99 added a comment - 09/Dec/11 09:00 PM

A common usage pattern is <h:commandLink> with execute=@this.

I'm often hitting this issue when the component I want updated was actually valid, but had been submitted previously with some other invalid component using execute=@form.


arjan tijms added a comment - 11/Dec/11 10:13 AM

It would be absolutely great if the enhancement BalusC requests could be implemented. This is an often recurring source of confusion when working with AJAX and multiple dialogs.

See this for another related source: http://community.jboss.org/message/620000


Ed Burns added a comment - 14/Dec/11 05:29 PM

I am open to changing the spec for this, but I must ask, if you want to render the component, why is it not listed in a "render" attribute?


wrschneider99 added a comment - 14/Dec/11 05:34 PM

at least in my case, the component that I want updated is in a "render" attribute, and is being re-rendered as a partial update; the issue is that the value picked up during render is not refreshing from the model/backing-bean when I expected it to.


ova2 added a comment - 18/Mar/12 11:37 AM

Hi. I'm not sure if we need this as standard behavior. Sometimes you want to preserve and sometimes reset values. Do you know ResetEditableValues component in PF Extensions? http://fractalsoft.net/primeext-showcase-mojarra/views/resetEditableValues.jsf Similar stuff exists in ADF Faces with <af:resetListener> and MyFaces Tomahawk, but pe:ResetEditableValues is much cleaner and better. It uses visitTree() to gather ResetEditableValues, by the way. I integrated this feature from pe:resetEditableValues into p:masterDetail first. As default built-in behavior. But after that I have figured out that there are use cases where we need to use JSF standard behavior and not to reset values. So, for pe:masterDetail I ended up with two attributes "preserveInputs" and "resetInputs". Here this use case (partially): http://fractalsoft.net/primeext-showcase-mojarra/sections/masterDetail/complexNavigation.jsf

"preserveInputs"
Specifies comma or blank separated list of clientIds of editable components whose inputs have to be preserved while levels get switched. @all is allowed and means all values within master detail have to be preserved. It makes sense e.g. if corresponding command component has "immediate"=true attribute. If nothing specified, input values gets cleared.

"resetInputs"
Specifies comma or blank separated list of clientIds of editable components whose inputs have to be cleared while levels get switched. @all is allowed and means all values within master detail have to be cleared. If takes precedence over clientIds in preserveInputs.

I wanted to say that this should be configurable when will be introduced into the core JSF stuff. In my opinion it's definitely better to use third-party components to achieve this behavior if it's desired. Please don't implement this feature as default behavior in JSF because we will end up then with a third-party component again. In this case with PreserveEditableValues (opposite of ResetEditableValues)

Thanks.
Oleg.


arjan tijms added a comment - 12/Apr/12 10:05 AM

Related discussion on the expert mailing list: http://java.net/projects/javaserverfaces-spec-public/lists/jsr344-experts/archive/2012-03/message/51

I'm not 100% sure for a pressing need for configurability in the AJAX case.

  • If a component is explicitly or implicitly targeted to be re-rendered (via the f:ajax render attribute), then it should be reset.
  • If the user wants to preserve values for some component, then this component should simply not be targeted for a re-render.

Yet another implementation of a reset listener: ResetInputAjaxActionListener.java

With quite a few implementations of the same concept out there and a recurring number of questions on this topic at e.g. the PrimeFaces forum and StackOverflow, I hope this can be considered for standardization.


ova2 added a comment - 12/Apr/12 01:57 PM

Hi Arjan,

Thanks for your reply. Saidly, but the default behavior, you described, doesn't satisfy all use cases. Imagine a component like PrimeFaces Wizard or PrimeFaces Extensions MasterDetail (you already know them). They render itself. Imagine

<h:panelGroup id="rootElement">
... // some UI mask with input fields, buttons, etc.
</h:panelGroup>

span / div element with id="rootElement" gets re-rendered while masks are switched. All UI masks are placed below the element with id="rootElement". You don't even need any wizard like components. You can just include masks dynamically via <ui:include src="#{myBean.currentMaskPath}"/> and re-render <h:panelGroup id="rootElement">. Now imagine you have a select box in a mask "ABC" and want to show details to any selected item by click on one small icon next to the select box. Detail infos are placed in the mask "XYZ". You have to change masks, that means re-render the root element above. Right? But you want to be able to go back from the mask "XYZ" to the "ABC" and see your last input values. Last input values in the mask "ABC" should not go lost during switching (we have e.g. templates with 100+ fields). And what now? You can not switch masks by f:ajax process="rootElement" because if validation fails you can't go to the next mask. Validation should be ignored in this case. You can't switch masks by f:ajax process="@none" because input values will not be saved as submitted values. You should use immediate="true". immediate="true" allows to skip validation and preserve last input values.

You see, we re-render and process an area and all values inside of this area should not be reseted. This was one use case. By another use case when you save the current mask, the same area gets re-rendered and processed again, but all values inside of this area should be reseted. I hope I could describe the problem understandable. Thanks.

P.S. By the way, in your ResetInputAjaxActionListener.java if you visit all components with visitTree in order to find editable value holders, reject visiting for not rendered components first. Something like

if (!target.isRendered()) { return VisitResult.REJECT; }

I have a big experience with such kind of reseting. We figured out that if you have a DataTable with rendered="false" and you visit it, it's value gets evaluated - all DataTable rows are re-evaluated during iteration. This behavior has a big impact on performance. Not rendered components are not needed to be visited. Good luck.


balusc added a comment - 12/Apr/12 03:57 PM

ova2: re your PS, check the value of VISIT_HINTS constant.


ova2 added a comment - 12/Apr/12 04:03 PM

@balusc: oh, cool, nice. thanks for hints (overlooked them).


kito75 added a comment - 06/Jul/12 07:05 PM

I think it's definitely important that this be optional, as ova2 mentioned. There are some cases where form validation has failed, the form is being re-rendered via Ajax, and the user sees a validation error. Often in that case, you want to keep the old values. The use-case where you're more likely to want them reset is when you're only updating one or two fields in the form dynamically, or if you're performing an action that requires refreshing all of the fields (such as navigating to another record).


balusc added a comment - 06/Jul/12 07:14 PM - edited

@kito: the reset won't be performed when the input field is included in "execute" attribute which is normally the case if you explicitly need to process it. So I don't see your concern. Only when the input field is not included in "execute" but is included in "render", then a reset makes completely sense, otherwise you just wouldn't have included it in the "render".