voyent
Clearing form elements  XML
Forum Index -> General Help
Author Message
intercollector

Joined: 11/Jan/2008 00:00:00
Messages: 17
Offline


We're trying to setup clear/reset/cancel buttons on the majority of our pages. Unfortunately, as outlined here http://wiki.apache.org/myfaces/ClearInputComponents you have to manually clear or reset the elements. I'd like to use the parentComponent.getChildren().clear(); option, as it is the most general. I was hoping bind the ice:form component as the parentComponent using a binding variable and clear all the children from there. Here is my implementation:

JSPX:
Code:
 <ice:form binding="#{backingBean.form}">
 ...elements...
 <ice:commandButton type="Submit"  action="#{backingBean.cancel}" value="Cancel Changes" immediate="true"/>
 


BackingBean:
Code:
 		    public String cancel(){
 		    	if (form != null) form.getChildren().clear();
 		    	return Constants.CANCEL;
 		    }
 


Unfortunately, this does not clear the form elements. I've read through the options in this post: http://www.icefaces.org/JForum/posts/list/4179.page

But unfortunately none of those will work for us, as I don't want to have to bind or name each and every element in the whole application.

When debugging, the form element is not null, so form.getChildren().clear() is getting called, but it doesn't seem to clear the form elements.

Any ideas?
oleczek

Joined: 24/Jan/2007 00:00:00
Messages: 92
Offline


I use the following
Code:
     static public void clearSubmittedValues(Object obj) {
         if (obj == null || obj instanceof UIComponent == false)
             return;
         
         List chld = ((UIComponent)obj).getChildren();
         if (chld.size() != 0) {
             for (int i = 0; i < chld.size(); i++) {
                 clearSubmittedValues(chld.get(i));
             }
         }
         
         if (obj instanceof UIInput) {
             ((UIInput)obj).setSubmittedValue(null);
             ((UIInput)obj).setLocalValueSet(false);
         }
     }
 

and call it with
Code:
 clearSubmittedValues(form);
 


Olek
intercollector

Joined: 11/Jan/2008 00:00:00
Messages: 17
Offline


I've tried this, and end up with the same problem. I put a breakpoint, and it seems to be clearing the UIInput submittedValue ok, but the resulting page is still What phase of the request cycle are you calling clearSubmittedValues from?
intercollector

Joined: 11/Jan/2008 00:00:00
Messages: 17
Offline


Ok, I'm getting closer. This does seem to work:

Code:
		     private void clearSubmittedValues(Object obj) {
 		         if (obj == null || obj instanceof UIComponent == false)
 		             return;
 
 		         List chld = ((UIComponent)obj).getChildren();
 		         if (chld.size() != 0) {
 		             for (int i = 0; i < chld.size(); i++) {
 		                 clearSubmittedValues(chld.get(i));
 		             }
 		         }
 		         if (obj instanceof HtmlInputText) {
 		        	 ((HtmlInputText)obj).setSubmittedValue("");
 		         }else if (obj instanceof UIInput) {
 
 		         ((UIInput)obj).setSubmittedValue(null);
 		             ((UIInput)obj).setValue(null);
 		             ((UIInput)obj).setLocalValueSet(false);
 		         }
 		     }


Some really weird stuff going on if it's a text box. It doesn't seem to be related to icefaces, as the HtmlInputText.setSubmittedValue is a method in MyFaces. oleczek, are you using MyFaces?

In any event, this solves my issue for now. Also, for a go-forward approach, if I have any other element types that don't reset properly, I at least have the ability to deal with each type manually, like I did above.
oleczek

Joined: 24/Jan/2007 00:00:00
Messages: 92
Offline


I'm not using MyFaces, just straight IceFaces.
Since your input fields are HtmlInputText ,it makes perfect sense that you had to add 'if (obj instanceof HtmlInputText)' line.
The reason I have 'if' statement is that some elements might not be of UIInput type and calling setSubmittedValue will generate runtime exception.

Olek
intercollector

Joined: 11/Jan/2008 00:00:00
Messages: 17
Offline


Unfortunately, I'm having further problems with this solution. I've found an issue in that if I bind the form with this:

Code:
<ice:form binding="#{allowableCourseBean.form}" >


I get some odd behaviour. With this binding, every time the user navigates back to this page, all of my table headers and form labels on the page are rendered twice. Another navigation after that will show them rendered 3 times. It's odd because the form elements and any controls on the page are rendered just once. As soon as I remove that binding, the problem goes away. It's almost like it's not handling the DOM tree properly if the ice form is bound to a managed bean.

Is there some other way of retreiving the form other than binding it?

intercollector

Joined: 11/Jan/2008 00:00:00
Messages: 17
Offline


Sorry for the extra posts, but I have a final solution. Hopefully others will be able to make use of this.

Code:
 		    public final String reset(){
 		    	if (form != null) {
 		    		 clearSubmittedValues(form);
 		    	} else {
 		    		UIViewRoot viewRoot =(UIViewRoot)FacesContext.getCurrentInstance().getViewRoot();
 	    			UIForm form2 = findForm(viewRoot);
 		    		if (form2 != null){
 		    			clearSubmittedValues(form2);
 		    		}
 		    	}
 		    	return Constants.CANCEL;
 		    }
 		     private UIForm findForm(Object component) {
 		         if (component == null || component instanceof UIComponent == false)
 		             return null;
 		         List chld = ((UIComponent)component).getChildren();
 		         if (chld.size() != 0) {
 		             for (int i = 0; i < chld.size(); i++) {
 		            	 UIForm form = findForm(chld.get(i));
 		            	 if(form != null) return form;
 		             }
 		         }
 		         if (component instanceof UIForm) return (UIForm)component;
 		         else return null;
 			}
 			private void clearSubmittedValues(Object obj) {
 		         if (obj == null || obj instanceof UIComponent == false)
 		             return;
 
 		         List chld = ((UIComponent)obj).getChildren();
 		         if (chld.size() != 0) {
 		             for (int i = 0; i < chld.size(); i++) {
 		                 clearSubmittedValues(chld.get(i));
 		             }
 		         }
 		         if (obj instanceof UIInput) {
 
 		         ((UIInput)obj).setSubmittedValue(null);
 		             ((UIInput)obj).setValue(null);
 		             ((UIInput)obj).setLocalValueSet(false);
 		         }
 		     }
 
jgenoese

Joined: 13/Oct/2007 00:00:00
Messages: 18
Offline


I suggest a slight refactoring using 'getFacetsAndChildren()' instead of 'getChildren()'. Sometimes input components are inside facets, and for some reason, 'getChildren()' doesn't seem to return these.

I am deeply grateful for this solution. Many thanks.

John
intercollector

Joined: 11/Jan/2008 00:00:00
Messages: 17
Offline


Thanks for the tip. Definately will look into that refactor for our next release.

I'd also like to add one tidbit that I had to add. It's seems the findForms method I posted a bug doesn't work in some cases if there are multiple forms on the page, therefore I've modified this function as follows:

Code:
    
 private List<UIForm> findForms(Object component) {
         if ((component == null) || (component instanceof UIComponent == false)) {
             return null;
         }
         List<UIForm> forms = new ArrayList<UIForm>();
         List chld = ((UIComponent) component).getChildren();
 
         if (chld.size() != 0) {
             for (int i = 0; i < chld.size(); i++) {
             	List<UIForm> subForms = findForms(chld.get(i));
 
                 if (subForms != null && !subForms.isEmpty()) {
                     forms.addAll(subForms);
                 }
             }
         }
 
         if (component instanceof UIForm) {
         	forms.add((UIForm)component);
         }
         return forms;
     }
 
mchin

Joined: 11/Apr/2008 00:00:00
Messages: 9
Offline


Hello, I, too am very grateful for this solution. :)

Thank you so much
liming.wu

Joined: 26/Oct/2004 00:00:00
Messages: 441
Offline


There are a lot of ways to clear input components for clear/reset/cancel buttons.

1. make action return non-null navigation value. This causes new component tree, hence input components are "cleared". But remember there could be issue for beans which use phaseListener for initialization as the request is not postback any more.

2. explicitly clear up input components via component binding as intercollector mentioned above. It doesn't have to a form and it could be a container, which contains those input components.

Regarding setSubmittedValue, actually there is a convenient method specially for this purpose. UIInput.resetValue().

3. use ViewRoot.findComponent() to find container of input components (assume all input components are inside the container), and then loop through all UIInput/EditibleValueHolder to reset it.

FacesContext facesContext = FacesContext.getCurrentInstance();
UIViewRoot uiViewRoot = facesContext.getViewRoot();
UIComponent inputContainer = (UIComponent) uiViewRoot.findComponent("form1:tripPanel");

Regards

Liming Wu
[Email]
dpb1

Joined: 29/Jan/2009 00:00:00
Messages: 14
Offline


Since I have spent so long on this, I thought I would post my fix.

I used the collected code so far to do a "mass clear" of forms (icefaces should really provide this by default??), and to get it to work for icefaces, you need the clearSubmittedValues function modified as follows:

Code:
     private void clearSubmittedValues(Object obj) {
         if (obj == null || obj instanceof UIComponent == false) {
             return;
         }
 
         Iterator<UIComponent> chld = ((UIComponent) obj).getFacetsAndChildren();
         while (chld.hasNext()) {
             clearSubmittedValues(chld.next());
         }
         if (obj instanceof UIInput) {
             ((UIInput) obj).setSubmittedValue(null);
             ((UIInput) obj).setValue(null);
             ((UIInput) obj).setLocalValueSet(false);
             ((UIInput) obj).resetValue();
         }
     }
 


Basically, the getFacetsAndChildren has to be used. I think all icefaces input fields must be contained in facets.

Thanks for the original solution intercollector!
liming.wu

Joined: 26/Oct/2004 00:00:00
Messages: 441
Offline


Yes, it should work.
This tip is not specific for ICEfaces. It applies to SUN RI or MyFaces based app as well.

[Email]
 
Forum Index -> General Help
Go to:   
Powered by JForum 2.1.7ice © JForum Team