4 Replies Latest reply on Dec 20, 2009 6:54 AM by dsmithson

    Rerender a dynamic datatable with dynamic columns per table

      Hi all,

      I am having problems trying to rerender a dynamic datatable with dynamic columns, I need to be able to create multiple dynamic tables with each table consisting of 1 row (an object which contains a List) but containing dynamic columns determined by the size of the List in the table row object. I can create the tables and columns succesfully on entry to the page but when I try to add columns to the table via a Modal Panel the table is not being rerendered. The table and columns are built succesfully in the Java code but, like I said, the tables are not being rerendered to display the new number of columns.

      Thanks.

        • 1. Re: Rerender a dynamic datatable with dynamic columns per table
          panky_p

          Are you using reRender your table id on submitting values from your modal panel? make sure you rerender your table after adding column to it.

          Can you post some code snippet?

          • 2. Re: Rerender a dynamic datatable with dynamic columns per table

            HI,

            My code is as follows.....

             

            XHTML....

             

            Binding..

             

             

            ModalPanel which should render the bound table.....

             

             

             

            Java code to build dynamic tables and columns......

             

             

             

            As you can see if I was to define a tableID for rerendering from the modal panel I would have to create the modalPanel also in Java as the tables are dynamnic and therefore I dont know the Ids until runtime.

            • 3. Re: Rerender a dynamic datatable with dynamic columns per table

              HI,

              My code is as follows.....

               

              XHTML....

                   

               

              Binding..

              <rich:panel id="nonStdDataTablePanel" binding="#{nonStdDataTablePanel.nonStdDataTablePanel}">
                     </rich:panel>

               

               

              ModalPanel which should render the bound table.....

                  <rich:modalPanel id="addRetroTieredPanel" autosized="true" width="800">
                          <f:facet name="header">Add Stepped/Tiered Non Std Retrocession Financial Terms</f:facet>
                          <f:facet name="controls">
                              <h:panelGroup>
                                  <h:graphicImage value="/img/error.gif"
                                      id="retrotieredaddlinkamf" styleClass="hidelink"/>
                                  <rich:componentControl for="addRetroTieredPanel" attachTo="retrotieredaddlinkamf"
                                      operation="hide" event="onclick" />
                              </h:panelGroup>
                          </f:facet>
                          <h:form>
                             
                                <h:panelGrid columns="1" id="addTieredRetroPanelGrid" >
                              
                                        <div>
                        <h:messages/>
                       </div>
                               
                                                     
                       <s:label id="scaddtieredPanelamf" value="Share Class - #{marketingClassHome.instance.className}"/>
                             
                             
                              
                       <s:label id="fpaddtieredPanelamf" value="Fund Pool - #{retroHome.instance.fundPool.descr}" rendered="#{tieredRetroList.rowCount gt 0}"/>
                             
                                 
                                   
                        <h:panelGrid columns="2">
                       
                           
                                     
                             <s:label value="Range From - " />
                             <h:inputText value="#{retroHome.instance.rangeFrom}" />
                             <s:label value="Range To - " />
                         <h:inputText value="#{retroHome.instance.rangeTo}"/>
                             <s:label value="Rebate - " />
                             <h:inputText value="#{retroHome.instance.rebate}" />        
                            </h:panelGrid>
                                
                              
                          
                             
                             
                              <s:div id="addTieredRetroamfbutton">
                                                  
                                  <a4j:commandButton id="addamf" value="Add"
                                        reRender="tablePanel, paymenytccyField, reinvRetroRebate, nonstdamfPanel, addTieredRetroPanelGrid, nonStdDataTablePanel"
                                        action="#{retroHome.saveNonStdTieredRetro}"
                                        status="commonstatus"                                          
                                       >
                                       <f:setPropertyActionListener value="#{retroHome.instance.fundPool}"
                                                  target="#{retroHome.instance.fundPool}" />
                                   
                                        <f:setPropertyActionListener value='N'
                                                  target="#{retroTermsChargeTypeHome.instance.standardInd}" />
                                  </a4j:commandButton>
                                  <s:span>
                                       <a4j:commandButton value="Close"
                                               onclick="#{rich:component('addRetroTieredPanel')}.hide();return false;" />
                                </s:span>
                                 
                              </s:div>
                             
                             
                            
                              </h:panelGrid>
                          </h:form>
                  </rich:modalPanel>
               

               

               

               

              Java code to build dynamic tables and columns......

              @Name

               

              ("nonStdDataTablePanel")

              public

               

               

              private HtmlPanel nonStdDataTablePanel;

               

              private HtmlDataTable dataTable;

               

              private HtmlOutputText rowsExist;

               

               

              public void setNonStdDataTablePanel(HtmlPanel nonStdDataTablePanel) {

               

              this.nonStdDataTablePanel = nonStdDataTablePanel;

              }

               

               

              @Observer("refreshTieredRetroList")

               

              public HtmlPanel getNonStdDataTablePanel() {

               

              if(getDataTable(null, null)!=null){

              getDataTable(

              null, null).getChildren().clear();

               

              nonStdDataTablePanel.getChildren().clear();

              setDataTable(

              null);

              setNonStdDataTablePanel(

              null);

              }

               

               

               

               

              nonStdDataTablePanel = (HtmlPanel)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlPanel.COMPONENT_TYPE);

               

               

              Application app = FacesContext.getCurrentInstance().getApplication();

              ExpressionFactory elFactory = app.getExpressionFactory();

              ELContext elContext = FacesContext.getCurrentInstance().getELContext();

               

               

              //refresh list as this method to rebuild component is called before

               

              //the list is.

              RetroList retroList = (RetroList)Component.getInstance(

              "retroList");

              retroList.getTieredRetroList();

              ValueExpression listValue = Expressions.instance().createValueExpression(

              "#{tieredRetroList}");

               

               

               

               

              //test to see if rows are populated after adding

               

              //retro range

              ValueExpression listValueTest = Expressions.instance().createValueExpression(

              "#{tieredRetroList.wrappedData[0].retroRanges.size}");

               

              rowsExist = (HtmlOutputText)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlOutputText.COMPONENT_TYPE);

               

              rowsExist.setValueExpression("value", listValueTest.toUnifiedValueExpression());

               

              nonStdDataTablePanel.getChildren().add(rowsExist);

               

               

              List<Retro> tieredRetroList = (List<Retro>)((ListDataModel)listValue.getValue()).getWrappedData();

              Integer id=0;

               

              for(Retro retro : tieredRetroList){

               

              //for each fund pool get retros and add columns.....

               

              if(retro.getFundPool()!=null){

               

              nonStdDataTablePanel.getChildren().add(getDataTable(retro, id));

              id++;

              }

               

              }

               

               

              HtmlAjaxCommandButton addButton = (HtmlAjaxCommandButton)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlAjaxCommandButton.

              COMPONENT_TYPE);

              addButton.setAjaxSingle(

              true);

              addButton.setId(

              "addretroamfteredlink"+id);

              addButton.setValue(

              "Add");

              addButton.setOncomplete(

              "Richfaces.showModalPanel('addRetroTieredPanelForFundPool')");

              addButton.setReRender(

              "addRetroTieredPanelForFundPool");

               

              //nonStdDataTablePanel.getChildren().add(addButton);

               

               

              return nonStdDataTablePanel;

              }

               

               

              public HtmlDataTable getDataTable(Retro retro, Integer id){

               

              //for all retro ranges add columns using the rebate/discount as the header.

               

              if(retro != null){

               

              dataTable = (HtmlDataTable)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlDataTable.COMPONENT_TYPE);

              ELContext elcontext = FacesContext.getCurrentInstance().getELContext();

              Application application = FacesContext.getCurrentInstance().getApplication();

               

               

              dataTable.setVar("retro");

               

              dataTable.setId("nonstddataTable"+id);

              ExpressionFactory elFactory = application.getExpressionFactory();

               

               

              List<Retro> oneRowList =

              new ArrayList<Retro>();

              oneRowList.add(retro);

               

              dataTable.setValue(oneRowList);

               

              HtmlColumn fundPoolColumn =

              new HtmlColumn();

              HtmlOutputText fundPoolHeader =

              new HtmlOutputText();

              fundPoolHeader.setValue(

              "Fundpool");

              fundPoolHeader.setId(

              "Fundpoolheader"+id);

              fundPoolColumn.setHeader(fundPoolHeader);

              fundPoolColumn.setId(

              "Fundpool"+id);

               

               

               

              //ValueExpression fpve = elFactory.createValueExpression(elcontext, "#{retro.fundPool.descr}", String.class);

              HtmlOutputText fundPoolOutput =

              new HtmlOutputText();

              fundPoolOutput.setValue(retro.getFundPool().getDescr());

              fundPoolColumn.getChildren().add(fundPoolOutput);

               

              dataTable.getChildren().add(fundPoolColumn);

               

               

              //get retros for fundpool...

               

              //List<Retro> tieredRetroList = ((RetroList)Component.getInstance( "retroList")).getResultList();

               

               

               

              //add first column for reate/range from

              HtmlColumn dyncolumn = (HtmlColumn)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlColumn.

              COMPONENT_TYPE);

               

              // Create header (optional) and add to column.

              HtmlOutputText title = (HtmlOutputText)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlOutputText.

              COMPONENT_TYPE);

              title.setValue(retro.getRebate()+

              "%");

              title.setId(

              "firstcoltitle"+id);

              HtmlOutputText output = (HtmlOutputText)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlOutputText.

              COMPONENT_TYPE);

              output.setValue(

              ""+retro.getRangeFrom()+"m"+"-"+retro.getRangeTo()+"m");

              output.setId(

              "firstcoloutput"+id);

              dyncolumn.setHeader(title);

              dyncolumn.getChildren().add(output);

               

              dataTable.getChildren().add(dyncolumn);

               

               

              if(retro.getRetroRanges()!=null){

               

              for(int a=1; a<retro.getRetroRanges().size();a++){

               

              //for each fund pool get retros and add columns.....

              Retro retroObj = retro.getRetroRanges().get(a);

              HtmlColumn rrdyncolumn = (HtmlColumn)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlColumn.

              COMPONENT_TYPE);

               

              // Create header (optional) and add to column.

              HtmlOutputText rrtitle = (HtmlOutputText)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlOutputText.

              COMPONENT_TYPE);

              rrtitle.setValue(retroObj.getRebate()+

              "%");

              rrtitle.setId(

              "coltitle"+id+a);

              HtmlOutputText rroutput = (HtmlOutputText)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlOutputText.

              COMPONENT_TYPE);

              rroutput.setValue(

              ""+retroObj.getRangeFrom()+"m"+"-"+retroObj.getRangeTo()+"m");

              output.setId(

              "coloutput"+id+a);

              rrdyncolumn.setHeader(rrtitle);

              rrdyncolumn.getChildren().add(rroutput);

               

              dataTable.getChildren().add(rrdyncolumn);

              }

              }

               

               

              HtmlColumn dyncolumnaddbutton = (HtmlColumn)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlColumn.

              COMPONENT_TYPE);

               

              // Create header (optional) and add to column.

              HtmlAjaxCommandButton addButton = (HtmlAjaxCommandButton)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlAjaxCommandButton.

              COMPONENT_TYPE);

              addButton.setAjaxSingle(

              true);

              addButton.setId(

              "addretrotieredamfbtn"+id);

              addButton.setValue(

              "Add");

              addButton.setReRender(

              "addTieredRetroPanelGrid");

              addButton.setOncomplete(

              "Richfaces.showModalPanel('addRetroTieredPanel')");

              Class [] argtypes =

              new Class[1];

              argtypes[0] = retro.getClass();

              MethodExpression me = elFactory.createMethodExpression(elcontext,

              "#{retroNonStdFinTermsController.addNewRetro(retro)}", null, argtypes);

              addButton.setActionExpression(me);

               

               

               

               

              //HtmlAjaxCommandLink editLink = (HtmlAjaxCommandLink)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlAjaxCommandLink.COMPONENT_TYPE);

               

              //editLink.setAjaxSingle(true);

               

              //editLink.setId("editnnstdtieredretrolink");

               

              //editLink.setOncomplete("#{rich:component('editTieredRetroPanel')}.show()");

               

              //HtmlGraphicImage image = (HtmlGraphicImage)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlGraphicImage.COMPONENT_TYPE);

               

              //image.setValue("/img/edit.gif");

               

              //editLink.getChildren().add(image);

               

               

              HtmlActionParameter param = (HtmlActionParameter)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlActionParameter.

              COMPONENT_TYPE);

               

              RetroHome retroHome = (RetroHome)Component.getInstance(

              "retroHome");

              Retro retroTestInstance = retroHome.getInstance();

              retroTestInstance.setSeq(

              new Byte("0"));

              ValueExpression selectedRetro = Expressions.instance().createValueExpression(

              "#{retroHome.instance}", Retro.class);

              param.setValueExpression(

              "value", selectedRetro.toUnifiedValueExpression());

               

              //param.setValueBinding("value",application

               

              // .createValueBinding("#{retro}"))

              param.setName(

              "selectedRetro");

               

               

              ValueExpression retroInstance = Expressions.instance().createValueExpression(

              "#{retroHome.instance}", Retro.class);

              param.setAssignToBinding(retroInstance.toUnifiedValueExpression());

              addButton.getChildren().add(param);

               

              HtmlToolTip toolTip = (HtmlToolTip)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlToolTip.

              COMPONENT_TYPE);

              toolTip.setFor(addButton.getId());

              toolTip.setId(

              "tooltip"+id);

              toolTip.setValue(

              "Add additional ranges to Fund Pool");

              dyncolumnaddbutton.getChildren().add(addButton);

              dyncolumnaddbutton.getChildren().add(toolTip);

               

               

              dataTable.getChildren().add(dyncolumnaddbutton);

               

              dataTable.setRendered(true);

               

               

              }

               

               

               

              return dataTable;

               

              }

               

               

              public void setDataTable(HtmlDataTable dataTable){

               

              this.dataTable = dataTable;

              }

               

               

              public void setRowsExist(HtmlOutputText rowsExist) {

               

              this.rowsExist = rowsExist;

              }

               

              public HtmlOutputText getRowsExist() {

               

              rowsExist = (HtmlOutputText)FacesContext.getCurrentInstance().getApplication().createComponent(HtmlOutputText.COMPONENT_TYPE);

               

              rowsExist.setValue("Test");

               

              return rowsExist;

              }

               

               

              }

               

               

               

              As you can see if I was to define a tableID for rerendering from the modal panel I would have to create the modalPanel also in Java as the tables are dynamnic and therefore I dont know the Ids until runtime.

               

              The code works like this....

              THe user inputs values into the modal panel, that is then saved to the DB, when the bound panel is being built it retrieves that info from the DB and creates the dyanmic tables depending upon the size of the list from the DB.

              class NonStdDataTablePanel {

               

              • 4. Re: Rerender a dynamic datatable with dynamic columns per table

                also the bound panel is being rerendered as the updated number of rows from the List is output via the outputText, which means that problem lies with the datatable alone not being rerendered.

                thanks