5 Replies Latest reply on Feb 20, 2009 6:04 AM by koloale1

    rich:fileUpload breaks component binding logic

    koloale1

      Hello!
      In xhtml I have

      <h:panelGrid binding="#{bean.nodeContent}">
      (Bean is in the session scope) to which I want to add other components dynamically at runtime on some events. So I create and add new components to bean.nodeContent's children. All works perfectly unless I try to add rich:fileUpload and after upload is completed rerender panelGrid. In fileUploadListener method I clear children of panelGrid and add new ones, but after that setNodeContent(new HtmlPanelGrid) method is called twice with new component and changes made to panelGrid get lost. Btw I have noticed that rich:fileUpload component keeps sending ajax requests during uploading, I gues it causes reset of my component object for panelGrid.
      So my question is why setNodeContent() method is called after upload listener is completed? And do I choose the right solution for programmatically adding new components, I mean via component binding and changing its children.

      Many thanks for any thoughts,
      Alexey


        • 1. Re: rich:fileUpload breaks component binding logic
          koloale1

          Does anybody know why fileUpload send several requests after onuploadcomplete?

          • 2. Re: rich:fileUpload breaks component binding logic

            Can you please post your part of code here?

            • 3. Re: rich:fileUpload breaks component binding logic
              koloale1

              Here is my code (simplified as possible):

              public class DocBean {
               private HtmlPanelGrid nodeContent;
               private boolean uploaded = false;
              
               public void setNodeContent(HtmlPanelGrid nodeContent) {
               this.nodeContent = nodeContent;
               }
              
               public HtmlPanelGrid getNodeContent() {
               return nodeContent;
               }
              
               public void setUploaded(boolean uploaded) {
               this.uploaded = uploaded;
               }
              
               public void fillContentPanel() {
               nodeContent.getChildren().clear();
               if (!uploaded) {
               HtmlFileUpload fileUpload = new HtmlFileUpload();
               HtmlAjaxSupport ajaxSupport = new HtmlAjaxSupport();
               ajaxSupport.setEvent("onuploadcomplete");
               ajaxSupport.setReRender("nodeContent");
               fileUpload.getFacets().put("a4jsupport", ajaxSupport);
               fileUpload.setFileUploadListener(
               FacesContext.getCurrentInstance().
               getApplication().
               createMethodBinding("#{editBean.uploadFile}",
               new Class[]{UploadEvent.class}));
               nodeContent.getChildren().add(fileUpload);
               } else {
               HtmlOutputText result = new HtmlOutputText();
               result.setValue("Successful");
               nodeContent.getChildren().add(result);
               }
               }
              
               public String start() {
               fillContentPanel();
               return null;
               }
              }
              
              public class EditBean {
               private DocBean docBean;
               public void setDocBean(DocBean docBean) {
               this.docBean = docBean;
               }
               public void uploadFile(UploadEvent event) {
               docBean.setUploaded(true);
               docBean.fillContentPanel();
               }
              }
              

              view.xhtml
               <body>
               <h:form>
               <h:commandButton action="#{docBean.start}" value="Start"/>
               </h:form>
               <h:panelGrid id="nodeContent" style="width: 100%;"
               binding="#{docBean.nodeContent}" columns="1"/>
              </body>
              


              After uploading file the text "Successful" should appear but the same fileUpload component is rendered actually. Where is a problem?

              • 4. Re: rich:fileUpload breaks component binding logic

                At the first please wrap panel grid by the form:

                <h:form>
                 <h:panelGrid id="nodeContent" style="width: 100%;"
                 binding="#{docBean.nodeContent}" columns="1"/>
                </h:form>


                Then please see why your code is erroneus:
                1. After file was uploaded you remove fileUpload (and ajaxSuppot too !!) from component tree.
                2. Then fileUpload fires uploadcomplete event and support component sends ajax request. But it will not be processed because ajaxSupport component is already removed.

                To fix the issue add ajaxListesner for support component and change component tree there:

                /** DocBean.fillContentPanel */
                
                public void fillContentPanel() {
                 nodeContent.getChildren().clear();
                 if (!uploaded) {
                 HtmlFileUpload fileUpload = new HtmlFileUpload();
                 HtmlAjaxSupport ajaxSupport = new HtmlAjaxSupport();
                 ajaxSupport.setEvent("onuploadcomplete");
                 ajaxSupport.setReRender("nodeContent");
                 ajaxSupport.setActionListener(FacesContext.getCurrentInstance()
                 .getApplication().createMethodBinding("#{editBean.onuploadlistener}",
                 new Class[] { ActionEvent.class }));
                 fileUpload.getFacets().put("a4jsupport", ajaxSupport);
                 fileUpload.setFileUploadListener(FacesContext.getCurrentInstance()
                 .getApplication().createMethodBinding(
                 "#{editBean.uploadFile}",
                 new Class[] { UploadEvent.class }));
                 nodeContent.getChildren().add(fileUpload);
                 } else {
                 HtmlOutputText result = new HtmlOutputText();
                 result.setValue("Successful");
                 nodeContent.getChildren().add(result);
                 }
                 }
                
                
                
                
                public class EditBean {
                 private DocBean docBean;
                 public void setDocBean(DocBean docBean) {
                 this.docBean = docBean;
                 }
                 public void uploadFile(UploadEvent event) {
                 //docBean.setUploaded(true); // Don't touch component tree here
                 //docBean.fillContentPanel();
                 }
                
                 public void onuploadlistener(ActionEvent event) {
                 this.uploaded = true;
                 fillContentPanel();
                }
                }
                


                • 5. Re: rich:fileUpload breaks component binding logic
                  koloale1

                  Thank you Andrei very much for the elaborate answer and example, it works perfectly.