7 Replies Latest reply on Jul 9, 2010 5:38 AM by peterjca

    Getting selected row of ScrollableDataTable

    peterjca Newbie

      Hi,

       

      I've just joined this community as I've started using RichFaces 3.3.3 and JSF 1.2. Around 4 years ago I gained massive experience with MyFaces which I used to generate dynamic GUIs programatically at runtime to edit content whose structure a user could define at runtime. All good fun but annoying too.

       

      Again with RichFaces I'm creating a custom component programatically. The component provides a form in which to enter property values for a database query and displays the results, if any, in a scrollable data table. You can then select a row in the table for further processing. It is this last part that has stumped me. I'm obviously interested in getting the selected row (or, actually an ID/primary key of the object) back to the server.

       

      Some snippets of pertinent code follow.

       

      Here's my table creation:

       

      final HtmlScrollableDataTable dataTable = new HtmlScrollableDataTable();

      final String dataTableId = parent.getId() + "_resultstable";
      dataTable.setId(dataTableId);

      dataTable.setSelectionMode(SelectionMode.single);

      dataTable.setVar("myItem");

       

       

      Here's the AJAX support creation:

       

      final HtmlAjaxSupport ajaxRowClick = new HtmlAjaxSupport();
      ajaxRowClick.setId(dataTable.getId() + "rowClick");
      ajaxRowClick.setEvent("onselectionchange");

      dataTable.getFacets().put("a4jsupport", ajaxRowClick);

       

       

      Here's a first attempt at having a selection change callback to a backing bean and/or backing bean setter calls with the id of the object in the row (the id being a Long). This snippet of code successfully calls the selectionChanged(ActionEvent event) method but from the event I can't seem to get the "selectedRow" parameter. Also, the backing bean methods are not called at all (I know this because I've got some println statements in them).

       

      final MethodExpression actionExpr = expressionFactory
                      .createMethodExpression(elContext,
                              "#{policySearchBean.selectionChanged}", void.class,
                              new Class[] { ActionEvent.class });
      HtmlActionParameter actionParam = new HtmlActionParameter();
      actionParam.setId(ajaxRowClick.getId() + "_param1");
      actionParam.setName("selectedRow");
      final ValueExpression myExpr1 = expressionFactory
                      .createValueExpression(elContext, "#{myItem.policyId}",
                              Long.class);
      actionParam.setValueExpression("value", myExpr1);
      final ValueExpression myExpr2 = expressionFactory
                      .createValueExpression(elContext,
                              "#{policySearchBean.policyId}", Long.class);
      actionParam.setAssignToBinding(myExpr2);
      actionParam.setActionListener(actionExpr);
      ajaxRowClick.addActionListener(actionParam);

       

       

       

      My second try is the following:

       

      SetPropertyActionListener listener = new SetPropertyActionListener();
      final ValueExpression myExpr1 = expressionFactory.createValueExpression(elContext, "#{myItem.policyId}", Long.class);
      listener.setValue(myExpr1);
      final ValueExpression myExpr2 = expressionFactory.createValueExpression(elContext, "#{policySearchBean.policyId}", Long.class);
      listener.setTarget(myExpr2);

      ajaxRowClick.addActionListener(listener);

       

       

      This does call the setters in the backing bean but the IDs are always 0. I guess this is a JSF lifecycle issue.

       

      Note that I'm not using any of the "row var" stuff on the table. My custom tag is within an a4j:form tag.

       

      Sadly, as with MyFaces all those years ago, RichFaces doesn't really have any good documentation beyond reference material. Fundamentals such as getting the selected row index/object/ID shouldn't be this hard?!

        • 1. Re: Getting selected row of ScrollableDataTable
          peterjca Newbie

          Well, surprise surprise. No one can answer my fundamental question. I can't even get buttons or links to work in the scrollabledatatable which I was hoping would be a workaround. They simply refuse to call the server. I've tried action params and propertylisteners on buttons and links as per my first message.

           

          Sigh, 5 years later and JSF implementations are still  incredibly poor. Too much effort is being put into the bells and whistles  and not enough into actually getting the fundamentals to work properly and testing each release.

           

          At least my table looks good. That makes up for the lack of   functionality.

           

          Looks like I'm going to have to create my own working sortable,  scrollable and selectable table with my own data model.

          • 2. Re: Getting selected row of ScrollableDataTable
            Nick Belaevski Master

            Hi Peter,

             

            Well, surprise surprise. No one can answer my fundamental question.

            I can . Please "up" the post if nobody answered - sometimes it just get missed because of huge traffic.

             

            Here is the demo answering your question: http://livedemo.exadel.com/richfaces-demo/richfaces/scrollableDataTable.jsf?c=scrollableDataTable&tab=usage

             

            They simply refuse to call the server.

            There can be several issues causing this, e.g. model changes between requests, validation issues, etc. To start the diagnostics, please add PhaseTracker and check if all phases are passed.

            • 3. Re: Getting selected row of ScrollableDataTable
              peterjca Newbie

              Thanks for responding Nick but your pointer to the demo does not answer my question.

               

              Remember that I'm doing things programatically and not with a table tag on a page. One major difference between the tags and Java code is, for example, the selection binding. The setSelection on the scrollable table does not take a value expression but a Selection object. I also do not have a table binding on my backing bean as the bean is unaware of the implementation details of my widget other than providing a "configuration" for the widget (such as which properties to generate a form for).

               

              So, I am unable to relate the demo to which you allude to my situation.

               

              Using the row selection on the table with a SetPropertyListener calls the backing beans with a null policy Id (it's a Long). The PhaseTracker output shows the setter being called with output "Setting policy ID to 0". The runtime details are per my first message.

               

              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker beforePhase
              INFO: BEFORE RESTORE_VIEW(1)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker afterPhase
              INFO: AFTER RESTORE_VIEW(1)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker beforePhase
              INFO: BEFORE APPLY_REQUEST_VALUES(2)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker afterPhase
              INFO: AFTER APPLY_REQUEST_VALUES(2)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker beforePhase
              INFO: BEFORE PROCESS_VALIDATIONS(3)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker afterPhase
              INFO: AFTER PROCESS_VALIDATIONS(3)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker beforePhase
              INFO: BEFORE UPDATE_MODEL_VALUES(4)
              Setting policy ID to 0
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker afterPhase
              INFO: AFTER UPDATE_MODEL_VALUES(4)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker beforePhase
              INFO: BEFORE INVOKE_APPLICATION(5)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker afterPhase
              INFO: AFTER INVOKE_APPLICATION(5)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker beforePhase
              INFO: BEFORE RENDER_RESPONSE(6)
              07-Jul-2010 12:14:38 org.exadel.jsf.PhaseTracker afterPhase
              INFO: AFTER RENDER_RESPONSE(6)

              • 4. Re: Getting selected row of ScrollableDataTable (your demo doesn't work properly)
                peterjca Newbie

                By the way, the scrollable data table demo you pointed me to doesn't work:

                 

                1. Sort any of the columns into descending order i.e. anything other than the default.

                2. The selected object in the popup fails to take account of the sorting.

                • 5. Re: Getting selected row of ScrollableDataTable (your demo doesn't work properly)
                  Konstantin Mishin Novice

                  As I understood your main problem is to get selection in event listener. In this case try to use something like this: event.getComponent().getAttributes().get("selection")

                  • 6. Re: Getting selected row of ScrollableDataTable (your demo doesn't work properly)
                    peterjca Newbie

                    Oh I tried that last week. That gives me a selection of null unless I've set a Selection object on my datatable when I'm building it. If I've set the object I merely get the same Selection object back with no state in it. As I pointed out, I see no correspondence between your table tag and selection="#{...}" attribute and the reality of the Java table object which requires a Selection object and not a value expression.

                     

                    Actually, I think it's rather important that your sortable table demo pops up the wrong object when you sort the columns. Suggests the whole thing doesn't work at all to me. Perhaps you should fix that which may thenh fix mine and other's problems.

                     

                    Is there really no core RichFaces developer who understands creating dynamic scrollable datatables in Java and maintaining and accessing row selection  state? It's not looking hopeful....

                    • 7. Re: Getting selected row of ScrollableDataTable
                      peterjca Newbie

                      I've solved one of my problems now. I can get the selection on the server. The problem was that the ELContext was being mucked with. Once I stripped that out, the selection was available. However, throw column sorting into the mix and you can't determine what actually was selected. So do I need to construct a table model in my backing bean and bind that to the table value to enable me to work out the actual selected item (rather than returning a list of objects)? I noticed that there is a (from memory) ModifiableModel(?) within the table which encapsulates the sorted row keys. How on earth do I access that information?

                       

                      This was why I was wanting an easy way of transmitting one of the selected object's fields in an AJAX onselectchange event. I am unable to do this hence my original post.

                       

                      Going back to first principles and trying what functionality I want via tags in a page (rather than programatically) doesn't work.

                       

                      Anybody got a working tags example that demonstrates this working upon a row selection, not using a link or button?

                       

                      The following results in null being set on the backing bean property upon each row selection:

                       

                      <f:view>
                      <h:panelGroup id="body-div" styleClass="content-div">
                          <h:form id="myform">
                              <rich:scrollableDataTable rowKeyVar="rkv" width="100%" id="policyList"
                                  value="#{policySearchBean.storeDummyPolicies}" var="policy" sortMode="single">

                       

                                  <a4j:support event="onselectionchange" ajaxSingle="true">
                                      <f:setPropertyActionListener value="#{rkv}" target="#{policySearchBean.policy}"/>
                                  </a4j:support>

                       

                                  <rich:column sortable="true">
                                      <f:facet name="header">
                                          <h:outputText value="id" />
                                      </f:facet>
                                      <h:outputText value="#{policy.policyId}" />
                                  </rich:column>

                       

                                  <rich:column >
                                      <f:facet name="header">
                                          <h:outputText value="number" />
                                      </f:facet>
                                      <h:outputText value="#{policy.policyNumber}"  />
                                  </rich:column>

                       

                                  <rich:column >
                                      <f:facet name="header">
                                          <h:outputText value="client name" />
                                      </f:facet>
                                      <h:outputText value="#{policy.client.name}" />
                                  </rich:column>
                              </rich:scrollableDataTable>
                          </h:form>
                      </h:panelGroup>
                      </f:view>