Michael Heinen píše v St 28. 03. 2012 v 16:22 +0200: > Hi, > > thanks to Martin and Christan for your answers. > > Trinidad and primefaces are not used in my project so far. > I had a quick look and it seems that the tr:resetActionListener as well > as the primefaces extension must be attached to all commands and I have > nearly 600. So I am looking for a more generic way.
Interesting requirement. Try custom ActionListenerImpl. The default implementation is [1]. This code implements the "action" feature at h:commandButton/link. You can provide own implementation, find parent UIForm and clear all EditableValueHolder in this UIForm. This is generally faster as interating over whole UIViewRoot. Also submittedValues are part of application state and manipulation of those value is responsibility of invoke-application phase. Register your implementation in faces-config.xml as: <application> <action-listener>my.reset.action.Listener</action-listener> </application> [1] https://svn.apache.org/repos/asf/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ActionListenerImpl.java > > Christias solution did not work in detail in combination with richfaces > 4.2.Final. > The renderIds are not full qualified client ids and therefore component > lookups fail. > Moreover I would not reset self-rendered outputpanels with this approach. > > But I have a workaorund now. > I use also a PhaseListener that runs afterRestoreView phase over the > complete view tree(!) and resets all EditableValueOlders. > At first I thought this would cost too much performance to run over the > complete view and to do it on every request. > But to my surprise it takes only one millisecond on my dev machine. > > However I would prefer to reset only submitted components and only in > case of a validation/conversion error after rendering the invalid values > and before state saving. From my pov this should be done always > internally in JSF. > Or does it make any sense to keep the local/submitted values after a > conversion/validation error occured and after the response is rendered? > > Thanks again, > Michael > > > > Am 26.03.2012 17:35, schrieb Christian Beikov: > > Hey, > > > > the following PhaseListener implementation will do the trick, at least > > this is what I would expect that should be done by jsf in general. > > > > public class ResetInputPhaseListener implements PhaseListener { > > > > private static final Logger log = > > LoggerFactory.getLogger(ResetInputPhaseListener.class); > > > > @Override > > public void afterPhase(PhaseEvent pe) { > > if > > (pe.getFacesContext().getPartialViewContext().isAjaxRequest()) { > > Collection<String> renderIds = > > pe.getFacesContext().getPartialViewContext().getRenderIds(); > > UIViewRoot view = pe.getFacesContext().getViewRoot(); > > > > for (String renderId : renderIds) { > > UIComponent comp = findComponent(view, renderId); > > > > if (comp != null) { > > recursiveReset(comp); > > } else { > > log.warn("Could not find component with id '" + > > renderId + "' in view '" + view.getViewId() + "'"); > > } > > } > > } > > } > > > > /** > > * Originally taken from Mojarra implementation of UIComponentBase > > with the > > * addition of special checking when the NamingContainer is of the > > type UIForm. > > */ > > private UIComponent findComponent(UIComponent comp, String expr) { > > if (expr == null) { > > throw new NullPointerException(); > > } > > > > FacesContext ctx = FacesContext.getCurrentInstance(); > > final char sepChar = UINamingContainer.getSeparatorChar(ctx); > > final String SEPARATOR_STRING = String.valueOf(sepChar); > > > > if (expr.length() == 0) { > > // if an empty value is provided, fail fast. > > throw new IllegalArgumentException("\"\""); > > } > > > > // Identify the base component from which we will perform our > > search > > UIComponent base = comp; > > if (expr.charAt(0) == sepChar) { > > // Absolute searches start at the root of the tree > > while (base.getParent() != null) { > > base = base.getParent(); > > } > > // Treat remainder of the expression as relative > > expr = expr.substring(1); > > } else if (!(base instanceof NamingContainer)) { > > // Relative expressions start at the closest > > NamingContainer or root > > while (base.getParent() != null) { > > if (base instanceof NamingContainer) { > > break; > > } > > base = base.getParent(); > > } > > } > > > > // Evaluate the search expression (now guaranteed to be relative) > > UIComponent result = null; > > String[] segments = expr.split(SEPARATOR_STRING); > > for (int i = 0, length = (segments.length - 1); > > i < segments.length; > > i++, length--) { > > result = findComponent(base, segments[i], (i == 0)); > > // the first element of the expression may match base.id > > // (vs. a child if of base) > > if (i == 0 && result == null > > && segments[i].equals(base.getId())) { > > result = base; > > } > > if (result != null && (!(result instanceof > > NamingContainer)) && length > 0) { > > throw new IllegalArgumentException(segments[i]); > > } > > if (result == null) { > > break; > > } > > base = result; > > } > > > > // Return the final result of our search > > return (result); > > } > > > > private UIComponent findComponent(UIComponent base, String id, > > boolean checkId) { > > if (checkId && id.equals(base.getId())) { > > return base; > > } > > // Search through our facets and children > > UIComponent result = null; > > for (Iterator i = base.getFacetsAndChildren(); i.hasNext();) { > > UIComponent kid = (UIComponent) i.next(); > > // Special handling for UIForm because of the attribute > > prependId > > if (!(kid instanceof NamingContainer) || (kid instanceof > > UIForm && !((UIForm) kid).isPrependId() && !id.equals(kid.getId()))) { > > if (checkId && id.equals(kid.getId())) { > > result = kid; > > break; > > } > > result = findComponent(kid, id, true); > > if (result != null) { > > break; > > } > > } else if (id.equals(kid.getId())) { > > result = kid; > > break; > > } > > } > > return (result); > > > > } > > > > private void recursiveReset(UIComponent comp) { > > if (comp instanceof EditableValueHolder) { > > ((EditableValueHolder) comp).resetValue(); > > } > > > > for (Iterator<UIComponent> i = comp.getFacetsAndChildren(); > > i.hasNext();) { > > recursiveReset(i.next()); > > } > > } > > > > @Override > > public void beforePhase(PhaseEvent pe) { > > } > > > > @Override > > public PhaseId getPhaseId() { > > return PhaseId.RESTORE_VIEW; > > } > > } > > > > > > Am 26.03.2012 17:22, schrieb Martin Koci: > >> Hi, > >> > >> normal JSF behaviour (as you already know) is preserving and > >> resdisplaying the invalid input to allow re-type it later, for example: > >> '"12-14-200001" can be understood as date': a user can fix it with > >> minimal effort only by removing two additional zeros. > >> > >> The classic solution for your problem is [1] tr:resetActionListener or > >> [2] pe:resetEditableValues. Do those two solve your task or is it other > >> problem? > >> > >>> a) How do I get the JSF 1.2 behavior with 2.1? Is resetValue() the > >> wrong method? > >> > >> This is the right method. > >> > >> > >>> b) Ideally I would reset only the executed components instead of all > >>> input fields of the form. How can I determine them? > >>> With richfaces 3.3.3 I checked for request keys representing the > >>> submitted region or the ajaxSingle key. is there anything similar for > >>> ajax commands and JSF 2.1? > >> for example pe:resetEditableValues has attribute 'for' or the standard > >> key javax.faces.partial.execute says it. > >> > >> > >>> c) Shouldn't there be out of the box support for this szenario? > >> Yes, in JSF 2.2 will be such thing as pe:resetEditableValues in core (in > >> prefix f:) > >> > >> [1] > >> http://myfaces.apache.org/trinidad/trinidad-api/tagdoc/tr_resetActionListener.html > >> > >> > >> [2] > >> http://fractalsoft.net/primeext-showcase-mojarra/views/resetEditableValues.jsf > >> > >> > >> > >> Michael Heinen píše v Po 26. 03. 2012 v 15:22 +0200: > >>> So I would like to clear the component values AFTER rendering and > >>> BEFORE > >>> state saving. > >>> Is this possible at all? > >>> Or do I have any better alternatives with JSF 2.1? > >>> > >>> Thanks, > >>> Michael > >>> > >>> Am 26.03.2012 13:49, schrieb Michael Heinen: > >>>> Hi all, > >>>> > >>>> I refer to the problem described at: > >>>> https://cwiki.apache.org/confluence/display/MYFACES/Clear+Input+Components# > >>>> > >>>> > >>>> > >>>> Workflow: > >>>> 1) Form is submitted > >>>> 2) Validation or conversion fails > >>>> 3) Another command is clicked that loads new or "fresh" data into the > >>>> same area > >>>> Problem: > >>>> The data of request (1) is shown instead of (3) because the submitted > >>>> or local values of the components are not cleared after > >>>> validation/conversion error. > >>>> > >>>> Solution for JSF 1.2 > >>>> I patched com.sun.facelets.FaceletViewHandler and cleared the UIInput > >>>> components via resetValue() before the new state was saved. > >>>> As a result new (fresh) data was shown correctly and the submitted > >>>> value was also shown directly after the validation/conversion error. > >>>> > >>>> With JSF 2.1 this does not work the same way. > >>>> - I patched > >>>> org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView > >>>> > >>>> > >>>> - Before accessing the state manager I iterate over the > >>>> clientIdsWithMessages, determine the correspoding form and call > >>>> resetValue for all inputComponents. > >>>> - As a result new (fresh) data is shown correctly after step (3) > >>>> - But the submitted value is NOT shown directly after the > >>>> validation/conversion error (step 2). Instead the original value is > >>>> shown. > >>>> (e.g. User clears required value and submits form, message 'Field > >>>> must not be empty' is shown and field contains the original value > >>>> instead of being empty) > >>>> > >>>> Questions: > >>>> a) How do I get the JSF 1.2 behavior with 2.1? Is resetValue() the > >>>> wrong method? > >>>> b) Ideally I would reset only the executed components instead of all > >>>> input fields of the form. How can I determine them? > >>>> With richfaces 3.3.3 I checked for request keys representing the > >>>> submitted region or the ajaxSingle key. is there anything similar for > >>>> ajax commands and JSF 2.1? > >>>> c) Shouldn't there be out of the box support for this szenario? > >>>> > >>>> Used versions: > >>>> MyFaces 2.1.6 with partial state saving activated > >>>> Tomahawk2 1.1.11 > >>>> Richfaces 4.2.0 Final > >>>> > >>>> Regards, > >>>> Michael > >> > > >

