6 Replies Latest reply on Jul 27, 2007 8:51 AM by Yannick Lazzari

    RichFaces 3.0.2 dataTable ajaxKeys broken?

    Yannick Lazzari Newbie

      Hi all,

      I have a problem with a dataTable on which I'm trying to partially re-render some rows using the ajaxKeys attribute. I know it's been discussed serveral times on this message board but I just can't seem to make it work. I tried using the a4j:repeat component and it works, but something's wrong when I apply a similar logic inside a dataTable.

      Here's my template snippet:

      <h:form id="theForm">
       <h:outputText value="The list is empty." rendered="#{theList.size == 0}"/>
       <rich:dataTable id="theTable" value="#{theList}" var="item" rendered="#{theList.size > 0}" ajaxKeys="#{myController.ajaxKeys}">
       <a4j:support event="onRowDblClick" action="#{myController.onDoubleClickItem}" reRender="theTable"/>
       <rich:column>
       <f:facet name="header">Col 1</f:facet>
       <h:outputText value="#{item.col1}" rendered="#{not item.editFlag}"/>
       <h:inputText value="#{item.col1}" rendered="#{item.editFlag}"/>
       </rich:column>
       <rich:column>
       <f:facet name="header">Col 2</f:facet>
       <h:outputText value="#{item.col2}" rendered="#{not item.editFlag}"/>
       <h:inputText value="#{item.col2}" rendered="#{item.editFlag}"/>
       </rich:column>
       <rich:column>
       <f:facet name="header"></f:facet>
       <a4j:commandLink value="Save" action="#{myController.saveSelectedItem}" reRender="theTable"/>
       </rich:column>
       </rich:dataTable>
      </h:form>
      


      Basically, when I double-click on a row, I want that particular row to be re-rendered so that it toggles between being editable or not; inline-editing pattern if you wish.

      My template is backed up by a stateful session bean that act as a Seam controller and listens to page events ("myController"). Here's what it looks like (only the important parts were included):

      @Stateful
      @Name("myController")
      public class MyControllerBean implements MyController {
      
       @DataModel
       private List<Item> theList;
      
       @DataModelSelection
       private Item selectedItem;
      
       private Set ajaxKeys;
      
       ...
      
       public void onDoubleClickItem() {
       selectedItem.setEditFlag(true);
       int i = theList.indexOf(selectedItem);
       Set ajaxKeys = new HashSet();
       ajaxKeys.add(i);
       setAjaxKeys(ajaxKeys);
       }
      
       public void saveSelectedItem() {
       selectedItem.save();
       selectedItem.setEditFlag(false);
       int i = theList.indexOf(selectedItem);
       Set ajaxKeys = new HashSet();
       ajaxKeys.add(i);
       setAjaxKeys(ajaxKeys);
       }
      
       public Set getAjaxKeys() {
       return ajaxKeys;
       }
      
       public void setAjaxKeys(Set ajaxKeys) {
       this.ajaxKeys = ajaxKeys;
       }
      
       ...
      
      }
      


      Now, the problem that I have is that it always re-renders the whole table when I double click on a row or click save on a row that is in edit mode. It doesn't really affect the functionality of the screen but I don't understand why it does so. Actually, I kind of do because I put a breakpoint on my "myController.getAjaxKeys()" method and it never gets called. That can't be good now, can it?! I don't understand why. I tried a similar pattern but using an a4j:repeat tag and it works. The "myController.getAjaxKeys()" method is called and only the "selectedItem" is re-rendered. What this tells me is that the functionality in Ajax4jsf works so it's probably something in RichFaces' dataTable or my way of using it. Can anyone help me? I'm currently using the snapshot of July 25th for both Ajax4jsf and RichFaces but I have the same problem with older snapshots as well.

      Thank you very much for any help on the matter.

        • 1. Re: RichFaces 3.0.2 dataTable ajaxKeys broken?
          Sergey Smirnov Master

          does it change something if you remove rendered="#{theList.size > 0}" from the dataTable?

          • 2. Re: RichFaces 3.0.2 dataTable ajaxKeys broken?
            Yannick Lazzari Newbie

            I just tried and nope. Was it a wild or an educated guess?

            • 3. Re: RichFaces 3.0.2 dataTable ajaxKeys broken?
              Sergey Smirnov Master

              I do not try my time for wild guesses.

              • 4. Re: RichFaces 3.0.2 dataTable ajaxKeys broken?
                Yannick Lazzari Newbie

                I just want to clarify that I didn't mean it in a bad way.

                • 5. Re: RichFaces 3.0.2 dataTable ajaxKeys broken?
                  Sergey Smirnov Master

                  The reason for ajaxKeys is to render only particular rows when you point to the component inside one of the column. As soon as your reRender pointers to the whole table, the whole table is re-rendered. Invoking AjaxKeys does not make sense here. This is a reason the method is not called.

                  • 6. Re: RichFaces 3.0.2 dataTable ajaxKeys broken?
                    Yannick Lazzari Newbie

                    OK, I got it working. I did what you said and changed the value of my reRender attribute not to point to the whole table. Since re-rendering a rich:column directly doesn't appear to be possible (I tried with a rich:columnGroup too but that didn't work either), I had to create a h:panelGroup inside each column, assign it an id and modify the value of my reRender attribute to list the id's of all the panel groups (since I want to reRender the whole row).

                    The reason I didn't do that in the first place is because of what the RichFaces Developer guide says about the ajaxKeys attribute on rich:dataTable:

                    6.28. How to reRender only particular row(s) of dataTable?
                    
                    If you use <rich:dataTable> then you may use ajaxKeys attribute to bind the rowKeys to be reRendered there. After you need to point reRender on the whole table and only specified rows will be reRedered.
                    


                    Unless I understand this wrong, it says that you should have your reRender point to the whole table and that's pretty much what I did the first time. Also, when I wanted to look at the source code of the rich:dataTable Flexibility example on the wiki (http://labs.jboss.com/wiki/RichFacesArticleDataTable) , I noticed that the link it provided to the source code was dead: http://anonsvn.jboss.org/repos/richfaces/trunk/richfaces-samples/richfaces-art-datatable. I really didn't search hard enough because as I'm writing this, I found where it was moved: http://anonsvn.jboss.org/repos/richfaces/trunk/samples/richfaces-art-datatable. Unfortunately, even this example doesn't make use of the ajaxKeys attribute.

                    All in all, I got everything working. But I would like to make some comments if you don't mind. I think that even though the behaviour described in section 6.28 of the RichFaces Developer's Guide doesn't appear to be implemented, I think it makes sense that it would work that way. If you specify to re-render a table component, I don't see any problem in it deciding to only partially refresh itself if it was told to (using the ajaxKeys attribute). What I don't like with my current solution (or "like less" I should say), is that I can't tell it to refresh the whole row at once. I need to enumerate all the columns; and actually, it's not even columns that I'm enumerating but a list of h:panelGroup's, each of which is the first child of a rich:column. Was it planned to eventually support the re-rendering a rich:column by specifying its id in a reRender attribute value? Or is there a way to specify one id for the whole row?

                    As always, thanks again for your help. We will never say it enough but your support is always greatly appreciated.