9 Replies Latest reply on Feb 12, 2009 10:34 AM by Florian Duehring

    Creating HtmlDataTable + Subtable programmatically / Problem

    Florian Duehring Newbie

      Hi,

      when I try to create a HtmlDataTable progrmmatically and than add a HtmlSubTable, the getRowData()-method of the sub table doesn't work as expected.
      Here's the code I have in the view:

      <rich:dataTable id="dtb_frm_content" binding="#{report.reportItemsTable}" />
      


      And here's the code if have in the getReportItemsTable of the backing bean:
      //create data table
      this.reportItemsTable = new HtmlDataTable();
      //set the value of the table => a list of OrderedReportRow-objects (see below)
      this.reportItemsTable.setValue(this.getOrderedReportRowOfCurrentReport());
      //add columns to datatable:
      ...
      
      //create sub table and set value expression
      this.subTable = new HtmlSubTable();
      ValueExpression valueExpressionForOrderedReportRows = FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(
       FacesContext.getCurrentInstance().getELContext(),
       "#{orderedReportRow.reportRows}",
       ArrayList.class
       );
      
      this.subTable.setValueExpression("value", valueExpressionForOrderedReportRows);
      //add columns to sub table
      ...
      
      //create column for an edit link
      HtmlColumn columnEdit = new HtmlColumn();
      //add link to column to edit
      HtmlAjaxCommandLink linkEdit = new HtmlAjaxCommandLink();
      linkEdit.setId("edit");
      linkEdit.setValue("edit");
      linkEdit.setActionExpression(
       FacesContext.
       getCurrentInstance().
       getApplication().
       getExpressionFactory().
       createMethodExpression(
       FacesContext.getCurrentInstance().getELContext(),
       "#{report.editRowStart}",
       String.class,
       new Class[0]
       )
       );
      
      //add edit column to sub table
      subTable.getChildren().add(columnEdit);
      
      //add sub table to table
      this.reportItemsTable.getChildren().add(subTable);
      


      When I click the edit link, the editRowStart()-method is called as expected:

      public void editRowStart(){
       this.currentRow = (ReportRow)this.subTable.getRowData();
      }


      But the row is set correctly only the first time, when I click the edit link in another row, the currentRow is still the same than after the first click. I think I have to bind the subtable to the backing bean, but I couldn't find a setBinding-attribute in the SubTable class (although I know that a binding attribute exists for the subTable-tag).

      Can anybody help me with this?

      Thanks

        • 1. Re: Creating HtmlDataTable + Subtable programmatically / Pro
          Nick Belaevski Master

          Hello,

          I guess the problem is happening because you haven't set var="orderedReportRow" for data table component. Please try that. Please post full bean code for investigation if that's not the cause.

          • 2. Re: Creating HtmlDataTable + Subtable programmatically / Pro
            Florian Duehring Newbie

            Hi,

            thanks for your answer. I set the var-attribute:

            this.reportItemsTable.setVar("orderedReportRow");


            I just forgott to post it. Actually the display of the rows is correct, just when I want to select the current row with

            subTable.getRowData()


            it fetched the correct line just once. So there must be another reason for this.

            Thanks

            • 3. Re: Creating HtmlDataTable + Subtable programmatically / Pro
              Florian Duehring Newbie

              no ideas? Here's the complete source of the getReportItemsTable-method

              public HtmlDataTable getReportItemsTable() {
               this.getCurrentReport();
               this.getOrderedReportRowOfCurrentReport();
               //create datatable
               this.reportItemsTable = new HtmlDataTable();
              
               this.reportItemsTable.setStyle("width:1200px");
               this.reportItemsTable.setValue(this.getOrderedReportRowOfCurrentReport());
               this.reportItemsTable.setVar("orderedReportRow");
              
              
               int i = 0;
               for (ReportColumn reportColumn : this.getCurrentReport().getColumns()) {
               HtmlOutputText header = new HtmlOutputText();
               header.setValue(reportColumn.getColumnName());
               header.setTitle(reportColumn.getColumnName());
               HtmlColumn column = new HtmlColumn();
               column.setId("reportItemsTableColumn_" + reportColumn.getColumnOrderNr());
               column.setHeader(header);
               column.setSortable(true);
               column.setSelfSorted(true);
               column.setLabel(reportColumn.getColumnName());
               column.setSortable(true);
              
              
               this.reportItemsTable.getChildren().add(column);
               i++;
               }
              
               HtmlColumn columnHeader = new HtmlColumn();
               columnHeader.setColspan(this.getCurrentReport().getColumns().size());
               columnHeader.setBreakBefore(true);
              
               HtmlOutputText columnHeaderOutput = new HtmlOutputText();
               ValueExpression valueExpressionColumnHeaderOutput = FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(
               FacesContext.getCurrentInstance().getELContext(),
               "<b>#{orderedReportRow.value}</b>",
               String.class
               );
               columnHeaderOutput.setValueExpression("value", valueExpressionColumnHeaderOutput);
               columnHeaderOutput.setEscape(false);
              
               columnHeader.getChildren().add(columnHeaderOutput);
              
               this.reportItemsTable.getChildren().add(columnHeader);
              
               subTable = new HtmlSubTable();
              
               ValueExpression valueExpressionForOrderedReportRows = FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(
               FacesContext.getCurrentInstance().getELContext(),
               "#{orderedReportRow.reportRows}",
               ArrayList.class
               );
              
               subTable.setValueExpression("value", valueExpressionForOrderedReportRows);
               subTable.setVar("reportRow");
              
               Integer j = 0;
               for (ReportColumn reportColumn : this.getCurrentReport().getColumns()) {
              
               HtmlColumn column = new HtmlColumn();
               column.setId("reportItemsTableColumnOrdered_" + j);
              
              
               ValueExpression valueExpression = FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(
               FacesContext.getCurrentInstance().getELContext(),
               "#{reportRow.cells[" + j + "].value}",
               String.class
               );
               HtmlOutputText output = new HtmlOutputText();
               output.setValueExpression(
               "value",
               valueExpression
               );
               output.setConverter(new NewlineConverter());
               output.setEscape(false);
               column.getChildren().add(output);
               subTable.getChildren().add(column);
              
               j++;
               }
               //set edit column
               HtmlColumn columnEdit = new HtmlColumn();
               columnEdit.setId("reportItemsTableColumn_dt_edit");
               columnEdit.setSortable(true);
               columnEdit.setSelfSorted(true);
               columnEdit.setLabel("");
              
               HtmlAjaxCommandLink linkEdit = new HtmlAjaxCommandLink();
               linkEdit.setId("edit");
               linkEdit.setValue("edit");
               linkEdit.setActionExpression(
               FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createMethodExpression(
               FacesContext.getCurrentInstance().getELContext(),
               "#{report.editRowStart}",
               String.class,
               new Class[0]
               )
               );
               linkEdit.setOncomplete("Richfaces.showModalPanel('mdp_createNewRow')");
               linkEdit.setReRender("frm_mdp_createNewRow");
              
               columnEdit.getChildren().add(linkEdit);
               subTable.getChildren().add(columnEdit);
               this.reportItemsTable.getChildren().add(subTable);
               return reportItemsTable;
               }


              ..and the tag in my xhtml file

              <rich:dataTable id="dtb_frm_content" binding="#{report.reportItemsTable}" />


              ..and the code of the editRowStart-method

              public void editRowStart(){
               this.currentRow = (ReportRow)this.subTable.getRowData();
               }


              Any help would be appreciated.

              Thanks

              • 4. Re: Creating HtmlDataTable + Subtable programmatically / Pro
                Ilya Shaikovsky Master

                what is the scope of your report bean?

                • 5. Re: Creating HtmlDataTable + Subtable programmatically / Pro
                  Florian Duehring Newbie

                  Hi,

                  the report bean has session scope. I already tried to use a normal datatable (without subtable), this worked as expected.

                  • 6. Re: Creating HtmlDataTable + Subtable programmatically / Pro
                    Ilya Shaikovsky Master

                    components should be bound to request scope beans. And this is not a limitation of RF framework. you could use google to check that session scoped bindings has many problems in JSF itself.

                    • 7. Re: Creating HtmlDataTable + Subtable programmatically / Pro
                      Florian Duehring Newbie

                      Hi,

                      I tried what you proposed (use request scope) with a4j:keepAlive, but the problem still exists.
                      I figured out that the getRowData()-method of the subTable which is used in the method editRowStart() always returns the first element of the sublist...

                      • 8. Re: Creating HtmlDataTable + Subtable programmatically / Pro
                        Ilya Shaikovsky Master

                        No.. binding should be request scoped. remove keep alive. If you have some data inside this bean also - split this bean to two. One session scoped for data and the second request scoped for view bindings.

                        • 9. Re: Creating HtmlDataTable + Subtable programmatically / Pro
                          Florian Duehring Newbie

                          Hi ilya_shaikovsky,

                          thanks a lot, now it works.