1 2 Previous Next 18 Replies Latest reply on Jan 23, 2009 1:51 PM by ssilvert

    How to access cell of

    wolfgangknauf

      Hi,

      I have a "h:dataTable" and want to loop over it to find a specific item.
      The table contains four columns: ID ("h:outputText"), a "h:outputText" field with id = "name", and two forms (one with an edit link, the other with a delete link).

      I loop over the table and compare the "name" values:

      HtmlDataTable table = (HtmlDataTable) this.server.findComponent("mytable");
      for (int iRow = 0; iRow < table.getRowCount(); iRow++)
      {
       Object objName = this.server.getComponentValue("mytable:" + iRow + ":name");
      }


      This returns "NULL".

      Now, I add this:
      HtmlDataTable table = (HtmlDataTable) this.server.findComponent("mytable");
      for (int iRow = 0; iRow < table.getRowCount(); iRow++)
      {
       table.setRowIndex(iRow);
       Object objName = this.server.getComponentValue("mytable:" + iRow + ":name");
      }

      And suddenly, the name is valid.

      Is this the intended behavior, or is the JSF datatable not initialized properly?


      This code snippet also returns NULL for the value of the textfield (though it finds the component for the ID):
      HtmlOutputText outputText = (HtmlOutputText) this.server.findComponent("mytable:" + iRow + ":name");
      System.out.println ("Value of text field: " + outputText.getValue());

      With "setRowIndex" the component value is valid.

      Thanks

      Wolfgang

        • 1. Re: How to access cell of
          ssilvert

          That's strange. I haven't seen that behavior. What JSF implementation are you using?

          Note that you will only be able to see rows that were actually displayed. This limitation in JSFUnit was due to a performance trade-off.
          https://jira.jboss.org/jira/browse/JSFUNIT-96

          Stan

          • 2. Re: How to access cell of
            wolfgangknauf

            Hi Stan,

            I use JBoss 5.0GA (which bundles Sun RI 1.2_10).

            I will try to create a sample.

            Best regards

            Wolfgang

            • 3. Re: How to access cell of
              wolfgangknauf

              Hi Stan,

              a sample is here:
              http://www.informatik.fh-wiesbaden.de/~knauf/private/JSFDataTable.war
              The WAR is created with eclipse/WTP, sources and JUnit JARs are inside. It is for JBoss 5.0GA.

              First, I try to access the table without "setRowIndex" => all component values are null.
              Second, I call "setRowIndex" for each row => correct values.
              Third is again a loop without "setRowIndex" => all rows have the values of the last "setRowIndex".

              I found that when accessing fields in a datatable, I always have to call "setRowIndex" first. Otherwise, getting the componentvalue through "this.server.getComponentValue("tablename.rowindex.fieldname");" will access the row at default rowindex "-1".
              So, the row does not seem to be resolved and auto-set by "getComponentValue"? Is it a JSF issue?

              Thanks

              Wolfgang

              • 4. Re: How to access cell of
                wolfgangknauf
                • 5. Re: How to access cell of
                  ssilvert

                  Thanks for the sample code. This should now be fixed. I'm uploading the snapshot now.

                  See https://jira.jboss.org/jira/browse/JSFUNIT-186

                  This was interesting. I was already caching all the displayed components, so JSFServerSession.findComponent() returned correctly. However, when you cast to ValueHolder and then call getValue() it would return null. The reason is because if there is no local value then it will execute the component's ValueBinding. Without setting the row ID, the ValueBinding.getValue() would return null.

                  With the new code JSFServerSession.findComponent() will still return the component as-is without setting a row ID.

                  But now when I cache the components I also keep track of the row ID for those components inside a UIData. If you call JSFServerSession.getComponentValue() then it will set the row ID, get the value, and then set the row ID back.

                  Please give it a try and let me know if it fixes your problem. As always, thanks for the feedback.

                  Stan

                  • 6. Re: How to access cell of 'h:dataTable'
                    wolfgangknauf

                    Hi Stan,

                    thanks for fixing it so fast! My sample works now.

                    But as I am nasty guy ;-), I tried it with tables in tables, and here it fails.
                    An updated sample is here: http://www.informatik.fh-wiesbaden.de/~knauf/private/JSFDataTable_Nested.war
                    I forgot to tell you with my last sample: the JSF can be viewed by browsing to http://localhost:8080/JSFDataTable

                    This is a code snippet to get the content of the nested table in main table row 1, sub-table row 1:

                    Object objNameNestedOne = this.server.getComponentValue("tablevalueobjects:1:tablenested:1:name");

                    It should return "Item 2_1", but it returns "Item 5_1".

                    Best regards

                    Wolfgang

                    • 7. Re: How to access cell of
                      ssilvert

                      Heh. Yea, that's nasty, but in a good way. I should be able to fix it soon.

                      Stan

                      • 8. Re: How to access cell of
                        ssilvert

                        I'm uploading a new snapshot. Nested Datatable should be working.

                        Stan

                        • 9. Re: How to access cell of
                          wolfgangknauf

                          Hi Stan,

                          I tested it with the new snapshot (take from jboss-jsfunit-examples-hellojsf-jsfunit-1.0.0.GA-20090115.152616-6.war).
                          But my sample still returns wrong values for "this.server.getComponentValue("tablevalueobjects:1:tablenested:1:name");"

                          Is the fix included in this version?

                          Thanks

                          Wolfgang

                          • 10. Re: How to access cell of
                            ssilvert

                            Sorry about that. The fix was wrong. I'm still working on it. Hopefully, I'll have something soon.

                            Stan

                            • 11. Re: How to access cell of
                              ssilvert

                              Hi Wolfgang,

                              I've uploaded a new snapshot and I'm pretty confident about it this time. I was keeping track of row indexes using a Hashtable which doesn't guarantee iteration order. So I changed to LinkedHashtable and made sure that I was calling setRowIndex() in the correct order for nested tables.

                              Your example still doesn't run perfectly. I think it might be a problem with your managed bean. Perhaps a setter is called by JSF and that messes it up for your nested table?

                              The reason a managed bean can cause a problem in this case is because when you call UIData.getValue() it executes EL that calls into the managed bean. So it is possible to get a different value each time you call it if something caused the backing bean to change.

                              I created a new test in the JSFUnit suite for nested tables. It has a read-only managed bean that can create a 3 x 3 table that can contain another table and so on down to arbitrary depth. The source is here:
                              http://anonsvn.jboss.org/repos/jsfunit/trunk/jboss-jsfunit-examples/jboss-jsfunit-examples-ajax4jsf/src/test/java/demo/Table.java

                              Here is the markup with a triple-nested table:
                              http://anonsvn.jboss.org/repos/jsfunit/trunk/jboss-jsfunit-examples/jboss-jsfunit-examples-ajax4jsf/src/main/webapp/pages/nestedtables.xhtml

                              And here is the test:
                              http://anonsvn.jboss.org/repos/jsfunit/trunk/jboss-jsfunit-examples/jboss-jsfunit-examples-ajax4jsf/src/test/java/org/jboss/jsfunit/example/ajax4jsf/NestedTableTest.java

                              The latest WAR snapshot is in this directory:
                              http://snapshots.jboss.org/maven2/org/jboss/jsfunit/jboss-jsfunit-examples-ajax4jsf/1.0.0.GA-SNAPSHOT/

                              The WAR runs on Tomcat 6, but you can get the three files above and run it in your project if you just declare this in your faces-config.xml:

                              <managed-bean>
                               <managed-bean-name>supertable</managed-bean-name>
                               <managed-bean-class>demo.Table</managed-bean-class>
                               <managed-bean-scope>request</managed-bean-scope>
                               </managed-bean>


                              Let me know what you think.

                              Regards,

                              Stan

                              • 12. Re: How to access cell of
                                wolfgangknauf

                                Hi Stan,

                                after more than two hours of trying to understand why your sample runs and mine doesn't, I got it: your sample builds wrong inner tables: all sub tables have the same values in relative sub table cells. So a call for row 2 in sub table 3 returns the same data as a call for row 2 in sub table 1.

                                I modified your table class to render the parent key plus child key:

                                public class Table
                                {
                                 /**Level of parent nest */
                                 private String parentKey;
                                 private int row;
                                
                                 public Table()
                                 {
                                 parentKey = "";
                                 row = -1;
                                 }
                                
                                 public Table(String parent, int row)
                                 {
                                 this.parentKey = parent;
                                 this.row = row;
                                 }
                                
                                 private String makeColumnName(String column)
                                 {
                                 String colName = "";
                                 //if (nestLevel > 0) colName += nestLevel + "_";
                                 if (parentKey.length() > 0) colName = parentKey + "_";
                                
                                 return colName + row + "_" + column;
                                 }
                                
                                 public String getColumn0()
                                 {
                                 return makeColumnName("0");
                                 }
                                
                                 public String getColumn1()
                                 {
                                 return makeColumnName("1");
                                 }
                                
                                 public String getColumn2()
                                 {
                                 return makeColumnName("2");
                                 }
                                
                                 public Table[] getSubTable()
                                 {
                                 String myNestLevel = "";
                                 //Append parent nest level:
                                 if (this.parentKey.length() > 0 && this.row != -1)
                                 {
                                 myNestLevel = parentKey + "_";
                                 }
                                 //Dont' add row on top level table:
                                 if (this.row != -1)
                                 {
                                 myNestLevel += this.row;
                                 }
                                 return new Table[] { new Table(myNestLevel, 0),
                                 new Table(myNestLevel, 1),
                                 new Table(myNestLevel, 2) };
                                
                                 }
                                }


                                I changed the first lines of your test to reflect those changes (rest of the test needs to be updated, too):
                                assertEquals( "1_1", server.getComponentValue("form:table:1:column1"));
                                 //assertEquals("1_2_1", server.getComponentValue("form:table:2:nestedtable:2:column1"));
                                 assertEquals("2_2_1", server.getComponentValue("form:table:2:nestedtable:2:column1"));
                                 //assertEquals("2_1_1", server.getComponentValue("form:table:0:nestedtable:0:nestednestedtable:1:column1"));
                                 assertEquals("0_0_1_1", server.getComponentValue("form:table:0:nestedtable:0:nestednestedtable:1:column1"))


                                Now it fails: "expected:<0_0_1_1> but was:<2_2_1_1>", which shows the same behaviour as my own sample: it returns always the data of the sub table of the LAST parent row.

                                Now it is up to you again ;-).

                                Wolfgang

                                • 13. Re: How to access cell of
                                  ssilvert

                                  Did you update to the latest snapshot?

                                  I made your suggested changes to my test. That's nice that each cell now corresponds to the client ID. But without any changes to JSFUnit core, it still passes for me.

                                  Stan

                                  • 14. Re: How to access cell of
                                    wolfgangknauf

                                    Hi Stan,

                                    I ran my sample on Tomcat 6 (including the MyFaces implementation of your "jboss-jsfunit-examples-ajax4jsf" sample). Here it worked fine, same for the modified NestedTable test. So maybe it is a problem with the Sun RI?

                                    Did you try to run the sample on JBoss 5 using the server default JSF implementation?

                                    Best regards

                                    Wolfgang

                                    1 2 Previous Next