1 2 Previous Next 15 Replies Latest reply on Jan 11, 2011 7:11 AM by cat_the_great

    rich:dataTable with dynamic columns

    Axel Motyka Newbie

      Iam new to richfaces, so maybe this is a simple problem - but i searched the forum i didnt found the right answer for me.
      The post is a little bit longer, but i hope everyone understands what i mean.

      My Problem is: I have a table with 2 default columns and some dynamic columns.
      In other words, a user selects a logbook -> an new LogbookReport is created and should be shown in the the dataTable. This specific logbook has always 5 dynamic columnes - other logbooks have 5 or more. But all logbooks have 2 fixed columns. I will add more "meta" data to LogbookReport later on - but that doesnt touch my problem.

      I built up a collection class for all values:

      public class LogbookReport {
      
       private List<LogbookReportRecord> records = null;
      
       public LogbookReport() {
       initRecords();
       }
      
       public List<LogbookReportRecord> getRecords() {
       return records;
       }
      
       public void setRecords(List<LogbookReportRecord> records) {
       this.records = records;
       }
      
       private void initRecords() {
       records = new ArrayList<LogbookReportRecord>();
       LogbookReportRecord rec;
       ArrayList<String> values = new ArrayList<String>();
       //Dynamic values
       values.add("10");
       values.add("100");
       values.add("1000");
       values.add("10000");
       values.add("10.10");
       rec = new LogbookReportRecord("01.01.2009", values, "Kommentar 1");
       records.add(rec);
      
       values = new ArrayList<String>();
       values.add("20");
       values.add("200");
       values.add("2000");
       values.add("20000");
       values.add("20.20");
       rec = new LogbookReportRecord("02.01.2009", values, "Kommentar 2");
       records.add(rec);
      
       }
      
      }


      And the values are:
      public class LogbookReportRecord {
       private String timestamp;
       private List<String> values = new ArrayList<String>();
       private String comment;
      
       public LogbookReportRecord() {
       }
      
       public LogbookReportRecord(String timestamp, List<String> values, String comment) {
       this.timestamp = timestamp;
       this.values = values;
       this.comment = comment;
       }
      
       public String getTimestamp() {
       return timestamp;
       }
      
       public void setTimestamp(String timestamp) {
       this.timestamp = timestamp;
       }
      
       public List<String> getValues() {
       return this.values;
       }
      
       public void setValues(List<String> values) {
       this.values = values;
       }
      
       public String getComment() {
       return comment;
       }
      
       public void setComment(String comment) {
       this.comment = comment;
       }
      }
      


      Then i try to show the data:
      <rich:dataTable var="record" value="#{logbookReport.records}">
      
       <rich:columnGroup>
       <rich:column>
       <h:outputText value="#{record.timestamp}" />
       </rich:column>
      
       <!-- for each wont work-->
       <c:forEach items="#{record.values}" var="value">
       <rich:column>
       <h:outputText value="#{value}" />
       </rich:column>
       </c:forEach>
      
       <!-- rich:columns wont work -->
       <!-- <rich:columns value="#{record.values}" var="value" index="index">
       <h:outputText value="#{value}" />
       </rich:columns>-->
      
       <rich:column>
       <h:outputText value="#{record.comment}" />
       </rich:column>
      </rich:columnGroup>
      
      </rich:dataTable>


      Where is my mistake?
      Is it not possible to iterate through a collection inside a collection?


        • 2. Re: rich:dataTable with dynamic columns
          Axel Motyka Newbie

          Ok this explains me that is not possible by c:forEach.

          But how is it possible? I think this is a common problem - so I thought there should be a solution.

          • 3. Re: rich:dataTable with dynamic columns
            Axel Motyka Newbie

            No hints here ?

            • 4. Re: rich:dataTable with dynamic columns
              Markus Zeltner Newbie

              try once something like:

              <rich:dataTable var="record" value="#{logbookReport.records}">
              
               <rich:columnGroup>
               <rich:column>
               <h:outputText value="#{record.timestamp}" />
               </rich:column>
              
               <rich:columns value="#{record.dynColumnLabels}" var="column" index="index">
               <f:facet name="header">
               <h:outputText value="#{column}" />
               </f:facet>
               <h:outputText value="#{record.dynColumnValues[index]}"/>
               </rich:columns>
              
               <rich:column>
               <h:outputText value="#{record.comment}" />
               </rich:column>
              </rich:columnGroup>
              
              </rich:dataTable>

              record.dynColumnLabels and record.dynColumnValues are both lists.

              hope that helps.

              /Markus

              • 5. Re: rich:dataTable with dynamic columns
                Axel Motyka Newbie

                @zeltner
                Ok this is the same problem.

                You have a managed bean logbook, inside you have a list with records logbookReport.records. This list is used for iteration.
                Every record has a additional list column in your example, value in my example.

                So the only difference between your example an my, is that you use the f:facet tag, which is only for naming. So far there is no difference between your example an my. And my version is not working.


                @nbelaevski

                You gave me a hint to c:forEach, maybe i missed something but what do you mean?

                @Thread
                I want to iterate through a list which includes a second list? How is this working? Should i use a4j for this?

                • 6. Re: rich:dataTable with dynamic columns
                  Andrei Markavtsov Apprentice

                  Hello axelmotyka.

                  We described in our dev guide that dynamic columns has one limitation for usage. Columns component reads value attribute on tag applying phase.
                  Data table component inits var request variable on render phase. So this value cannot be read by columns component because it was not initialized yet.

                  PLease move 'values' property from the 'LogbookReportRecord' class to 'LogbookReport '.

                  There are no any sense to define columns value for each row. It should defined for whole dataTable.

                  • 7. Re: rich:dataTable with dynamic columns
                    Axel Motyka Newbie

                    This is an example with a very complicated data model.

                    The problem is i only have n static columns, in this example timestamp and comment. Additionally i have m dynamic columns. During my sql selects i'am calculating how many dynamic columns i have. I cant do this in another way - the generated table depents on an datamodel which is used for many other applications, and is not perfect for my case. But the values are realtime values, so i cant create an new datamodel in the database.

                    So the example is some kind of logbook. This logbook always has 2 columns, and an amount of values which must be calculated. Cause of this iam trying to find a solution how such an example can be done with RichFaces.

                    If i rename values to columns and move it to LogbookReport, i have the dynamically names of my header columns. But i still need values for these columns - so i need the list values! And what i am trying to do, is to printout this list. And in my understanding of a class model it must be inside the LogbookReportRecord class.

                    How is this working in RichFaces, should i create a special function in my managed bean which creates these columns. And then should call this function by Ajax? Or is there a way without Ajax and the RichFaces components (or any other tag)?

                    • 8. Re: rich:dataTable with dynamic columns
                      Axel Motyka Newbie

                      i feel like an idiot...

                      Maybe someone is able to help me. Maybe my datamodel is shit, maybe I didnt understand dataTable - i dont know.
                      But with the hints inside this thread, the documentation and the examples i found - i am not able to understand the problem.

                      May datamodel:

                      public class LogbookReport {
                      
                       private List<LogbookReportRow> rows;
                       private List<String> columns;
                       private List<Double> totals;
                      }
                      
                      public class LogbookReportRow{
                       private String timestamp;
                       private List<String> values;
                       private String comment;
                      }
                      


                      All values will be inizialized when the constructor of LogbookReport is called.

                      Then i am trying to print out the datamodel in a dataTable. It should look like:
                      |Timestamp|Column 1|Column 2|...|Column N|Comments|
                      |04.02.2009|40|30|...|10|CommentToThisRow|
                      |04.02.2009|20|60|...|80|CommentToThisRow|
                      |04.02.2009|50|70|...|100|CommentToThisRow|
                      |Totals|110|160|....|190||

                      So used

                      <rich:dataTable var="row"value="#{logbookReport.rows}">
                      
                       <f:facet name="header">
                       <rich:columnGroup id="headerDynamicColumns">
                       <rich:columns value="#{logbookReport.columns}" var="column" index="index">
                       <h:outputText value="#{column}" />
                       </rich:columns>
                       </rich:columnGroup>
                       </f:facet>
                      
                       <!-- HERE SHOULD BE row.values IN A ROW -->
                       <!-- BUT HOW? -->
                       <!-- I tried it with forEach (as explained in the documentation) - didnt work-->
                       <!-- I tried it with columns - didnt work-->
                       <!-- I tried it with a subTable - and i got values but how can i print it with a dynamic length of row.values ?-->
                      
                       <f:facet name="footer">
                       <rich:columnGroup>
                       <rich:column>
                       <h:outputText value="Summe" />
                       </rich:column>
                       <rich:columns value="#{logbookReport.totals}" var="total"
                       index="index">
                       <h:outputText value="#{total}" />
                       </rich:columns>
                       <rich:column>
                       <h:outputText value="Count Comments" />
                       </rich:column>
                       </rich:columnGroup>
                       </f:facet>
                      
                      </rich:dataTable>
                      


                      Please, is anybody able to help me here - or can you show me what i did wrong?

                      • 9. Re: rich:dataTable with dynamic columns
                        Nick Belaevski Master

                        So, let's look at your case: you have several rows in LogbookReport - that's ok. Let us select the first one and draw it. How many columns should be rendered? You want their number to be equal to size of values collection + several columns for another fields. Imagine that we've rendered this number. Now we switch to the second row. How many columns should be rendered? And how can we assure that we get the same number as for the first row (it's table constraint)? We cannot. That's the reason this won't work.

                        • 10. Re: rich:dataTable with dynamic columns
                          Nick Belaevski Master

                          So, you need to know the number of columns. If you know it, voila:

                          <rich:dataTable value="#{report.records}" var="record">
                           <c:forEach begin="0" end="3" varStatus="status">
                           <rich:column>
                           <h:outputText value="#{record.values[status.index]}" />
                           </rich:column>
                           </c:forEach>
                           </rich:dataTable>

                          package table;
                          
                          import java.util.ArrayList;
                          import java.util.List;
                          import java.util.Random;
                          
                          public class Report {
                          
                           private static final int VALUES_LENGTH = 4;
                          
                           private List<Record> records = new ArrayList<Record>();
                          
                           public Report() {
                           for (int i = 0; i < 10; i++) {
                           String[] values = new String[VALUES_LENGTH];
                           for (int j = 0; j < values.length; j++) {
                           values[j] = String.valueOf(new Random().nextInt(17));
                           }
                          
                           records.add(new Record(values));
                           }
                           }
                          
                           public List<Record> getRecords() {
                           return records;
                           }
                          
                          }

                          package table;
                          
                          public class Record {
                          
                           private String[] values;
                          
                           public Record(String[] values) {
                           this.values = values;
                           }
                          
                           public String[] getValues() {
                           return values;
                           }
                          }


                          • 11. Re: rich:dataTable with dynamic columns
                            Andrei Markavtsov Apprentice

                            You can do the same case using dynamic columns:

                            <rich:dataTable value="#{report.records}" var="record">
                             <rich:columns begin="0" end="3" index="index">
                             <h:outputText value="#{record.values[index]}" />
                             </rich:columns>
                            </rich:dataTable>


                            • 12. Re: rich:dataTable with dynamic columns
                              Axel Motyka Newbie

                              Ok i changed my datamodel to a Array of Strings:

                              public class LogbookReport {
                              
                               private List<LogbookReportRow> rows;
                               private List<String> columns;
                               private List<Double> totals;
                              }
                              
                              public class LogbookReportRow{
                               private String timestamp;
                               private String[] values;
                               private String comment;
                              }
                              

                              LogbookReportRow.values is filled in LogbooReport constructor, all rows have the same values array length.

                              Then i try to print it out as you described:
                              <rich:dataTable value="#{logbookReport.rows}" var="row">
                               <rich:columnGroup>
                               <rich:column>
                               <h:outputText value="#{row.timestamp}" />
                               </rich:column>
                               <rich:columns begin="0" end="4" index="index">
                               <h:outputText value="#{row.values[index]}" />
                               </rich:columns>
                               <rich:column>
                               <h:outputText value="#{row.comment}" />
                               </rich:column>
                               </rich:columnGroup>
                              </rich:dataTable>
                              


                              All columns filled from row.values[index] are empty! If i access these rows without the index-var directly with a static int - it works! But not with the dynamic columns object and the same with forEach.
                              <h:outputText value="#{row.values[1]}" />


                              So i have the same managed bean code as you, same datastructure and same richfaces code. And it doesnt work! Iam using Richfaces 3.3.0GA.

                              • 13. Re: rich:dataTable with dynamic columns
                                Andrei Markavtsov Apprentice

                                Great sorry for the previous post.
                                It really does not work: https://jira.jboss.org/jira/browse/RF-6040.

                                Please use value attribute for the columns. You can create simple list or array with defined size filled by empty strings.

                                <rich:dataTable value="#{logbookReport.rows}" var="row">
                                <rich:columnGroup>
                                <rich:column>
                                <h:outputText value="#{row.timestamp}" />
                                </rich:column>
                                <rich:columns value="#{logbookReport.columns}" index="index">
                                <h:outputText value="#{row.values[index]}" />
                                </rich:columns>
                                <rich:column>
                                <h:outputText value="#{row.comment}" />
                                </rich:column>
                                </rich:columnGroup>
                                </rich:dataTable>


                                public class LogbookReport {

                                private List rows;
                                private List columns = Arrays.asList(new String [] {"","",""});;
                                private List totals;
                                }

                                • 14. Re: rich:dataTable with dynamic columns
                                  Axel Motyka Newbie

                                  Great! Big thanks for your help - now it is working!

                                  1 2 Previous Next