1 2 Previous Next 15 Replies Latest reply on Aug 6, 2009 9:51 AM by ilya_shaikovsky

    Clearing builtin filtering/sorting in rich:datatable

    smonty1

      Hi,
      I'm a developer working for first time with RichFaces and have been very impressed with the results so far.
      I've created a rich:datatable using the built in sorting/filtering (defined in the rich:column) and everything works great - the user selects search criteria (from optional droplists and input components outside the table), clicks a "Search" button and the table gets repopulated. The user is then able to use the inbuilt filtering/sorting to refine the table results. The filtering/sorting model state "sticks" when using the rich:datascroller to flick through the pages as well.
      I have a "Clear Search" button which resets the search criteria and reloads the table contents with the default search criteria. However I can't find a way of clearing any existing sorting/filtering selection the user might have done, prior to clicking on the "Clear Search" button... Is there any way of doing this programmatically without resorting to a tablemodel implementation?
      Some code snippets below:

      <rich:dataTable value="#{reconciliationTable.reconciliationList}"
      var="reconcItem" rows="#{searchCriteria.numRowsToDisplay}"
      reRender="ds" id="searchTable" rowKeyVar="row"
      columnsWidth="50,30,50,50,100,100,150,100,100,100,100,250,30" >

      <rich:column sortable="true" sortBy="#{reconcItem.id}"
      filterBy="#{reconcItem.id}" filterEvent="onkeyup">
      <f:facet name="header"> <h:outputText value="ID" />
      </f:facet>
      <h:outputText value="#{reconcItem.id}" />
      </rich:column>
      ....

      Thanks,
      Stephen

        • 1. Re: Clearing builtin filtering/sorting in rich:datatable
          kukeltje

          write some small custom javascript that clears the fields.

          • 2. Re: Clearing builtin filtering/sorting in rich:datatable
            smonty1

            Hi,
            Thanks for your reply. I wasn't too fussed in having any javascript (prefer to stick to JSF/java) in my app but implemented the following methods:

            function resetSearchTableFilters() {
             alert("resetSearchTableFilters called");
             var tags = document.getElementsByClassName("rich-filter-input");
             for ( var i = 0; i < tags.length; i++) {
             tags.value = "";
             }
             }
            
             // Javascript utility function to iterate through the DOM,
             // looking for those tags/elements that have a specified class
             // assigned to it.
             document.getElementsByClassName = function(clsName) {
             var retVal = new Array();
             var elements = document.getElementsByTagName("*");
             for ( var i = 0; i < elements.length; i++) {
             if (elements.className.indexOf(" ") >= 0) {
             var classes = elements.className.split(" ");
             for ( var j = 0; j < classes.length; j++) {
             if (classes[j] == clsName)
             retVal.push(elements);
             }
             } else if (elements.className == clsName)
             retVal.push(elements);
             }
             return retVal;
            }
            
            <a4j:commandButton id="clearSearchButton"
             value="#{msgs.clearSearchButtonLabel}"
             action="#{reconciliationTable.clearSearch}"
            reRender="searchTableAjax,searchCriteriaAjax,viewReconciliationResultsAjax"
             oncomplete="resetSearchTableFilters()">
            </a4j:commandButton>


            The only problem now is that when getting this new Javascript method to execute on the Clear button submit execution, doesn't give me the desired behaviour of all filters being cleared and full results being shown. Instead, using different calls of onclick, oncomplete, onbeforedomupdate etc (with/without requestDelay), causes:
            a. The filter values to disappear but then to be reappear (with the original filter values) after the AJAX request. The table view is unchanged.
            b. The filter values to be cleared (with oncomplete) but table view remains in the previous filtered view.

            All of this makes sense btw as essentially, i'm trying to put synchronous client JS behaviour into an async AJAX server request - not the best combination...

            Anyone any suggestions?

            Thanks,
            Stephen


            • 3. Re: Clearing builtin filtering/sorting in rich:datatable
              ilya_shaikovsky

              You could use filterValue and sortOrder bound to some bean property. And just reset the sort/filter values via action. It seems should be more native than just JS and request for storing them.

              • 4. Re: Clearing builtin filtering/sorting in rich:datatable
                kukeltje

                Yes, this latter is what I did as well after experimenting last week. I should have posted that additionally. I used the a4j:jsfunction to call a 'reset' method on the bean with the filterfields.

                • 5. Re: Clearing builtin filtering/sorting in rich:datatable
                  smonty1

                  Hi,
                  I'd left and then come back to this issue. I'm unable to get the filterValue working properly unfortunately. I created the relevant FilterBean POJO with a reset action method and am happy that the FilterBean value for the filter field is being used and then reset to a blank string value once reset action is performed. The table result set (and the table datascroller) gets refreshed correctly (ie same results as if no filters applied) but the actual filter input text field still contains the original value!?!
                  Any thoughts on why the filter field input text field doesn't get wiped?

                  Thanks,
                  Stephen





                  • 6. Re: Clearing builtin filtering/sorting in rich:datatable
                    ilya_shaikovsky

                    Add new problematic code.

                    • 7. Re: Clearing builtin filtering/sorting in rich:datatable
                      smonty1

                      Hi Ilya,
                      Thanks for taking the time to look at this.

                      <rich:column headerClass="smallFilter" sortable="true" sortBy="#{reconcItem.id}" filterBy="#{reconcItem.id}" filterValue="#{reconciliationTable.filterBean.idFilterValue}">
                       <f:facet name="header">
                       <h:outputText value="#{msgs.idColumnHeader}" />
                       </f:facet>
                       <h:outputText value="#{reconcItem.id}" />
                      </rich:column>


                      FilterBean simply contains String attribute idFilterValue (+setters/getters) and a reset method to set the idFilterValue String back to blank string "".

                      The #{reconciliationTable.clearSearch} action as seen in the a4j:commandButton code posted previously now calls the FilterBean's reset() method. As mentioned previously, from debugging text, I can see the idFilterValue value being reset correctly, it's just the "autogenerated" input filter textfield does not get reset on the Ajax request/update...

                      Thanks,
                      Stephen.


                      • 8. Re: Clearing builtin filtering/sorting in rich:datatable
                        ilya_shaikovsky

                        add ajaxSingle="true" to button.

                        • 9. Re: Clearing builtin filtering/sorting in rich:datatable
                          smonty1

                          Hi Ilya,
                          No luck with the ajaxSingle="true" clause - the filter input fields remain populated. I do have my table nested within an a4j:outputPanel and a rich:simpleTogglePanel, if that makes any difference?

                          <h:form id="searchTableForm">
                           <a4j:outputPanel id="searchTableAjax" >
                           <rich:simpleTogglePanel id="searchTableTogglePanel" label="Search Results" switchType="ajax" >
                           <rich:dataTable value="#{reconciliationTable.reconciliationList}"
                           ...
                          


                          • 10. Re: Clearing builtin filtering/sorting in rich:datatable
                            ilya_shaikovsky
                            • 11. Re: Clearing builtin filtering/sorting in rich:datatable
                              ilya_shaikovsky

                              reset button added to demosite.

                              <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                               xmlns:ui="http://java.sun.com/jsf/facelets"
                               xmlns:h="http://java.sun.com/jsf/html"
                               xmlns:f="http://java.sun.com/jsf/core"
                               xmlns:a4j="http://richfaces.org/a4j"
                               xmlns:rich="http://richfaces.org/rich">
                               <h:form>
                               <rich:dataTable value="#{capitalsBean.capitals}" var="cap" rows="20" reRender="ds" id="simpletable">
                               <f:facet name="header">
                               <rich:columnGroup>
                               <rich:column colspan="2" >
                               <h:outputText value="Filtering Example"/>
                               </rich:column>
                               <rich:column breakBefore="true">
                               <h:outputText value="State Name"/>
                               </rich:column>
                               <rich:column>
                               <h:outputText value="State Capital"/>
                               </rich:column>
                               </rich:columnGroup>
                               </f:facet>
                               <rich:column filterBy="#{cap.state}" filterEvent="onkeyup" filterValue="#{capitalsBean.currentStateFilterValue}">
                               <h:outputText value="#{cap.state}"/>
                               </rich:column>
                               <rich:column filterBy="#{cap.name}" filterEvent="onkeyup" filterValue="#{capitalsBean.currentNameFilterValue}">
                               <h:outputText value="#{cap.name}"/>
                               </rich:column>
                               <f:facet name="footer">
                               <rich:datascroller id="ds" renderIfSinglePage="false"></rich:datascroller>
                               </f:facet>
                               </rich:dataTable>
                               <a4j:commandButton action="#{capitalsBean.resetFilter}" value="Reset Current Filtering" reRender="simpletable" ajaxSingle="true" limitToList="true"/>
                               </h:form>
                              </ui:composition>

                              package org.richfaces.demo.capitals;
                              
                              import java.io.IOException;
                              import java.net.URL;
                              import java.util.ArrayList;
                              import java.util.Iterator;
                              import java.util.List;
                              
                              import javax.faces.FacesException;
                              import javax.faces.model.SelectItem;
                              
                              import org.apache.commons.digester.Digester;
                              import org.apache.commons.digester.xmlrules.DigesterLoader;
                              import org.xml.sax.SAXException;
                              
                              public class CapitalsBean {
                               private ArrayList<Capital> capitals = new ArrayList<Capital>();
                               private ArrayList<String> capitalsNames = new ArrayList<String>();
                               private List<SelectItem> capitalsOptions = new ArrayList<SelectItem>();
                               private String capital = "";
                              
                               private String currentStateFilterValue;
                               private String currentNameFilterValue;
                              
                               public List<Capital> autocomplete(Object suggest) {
                               String pref = (String)suggest;
                               ArrayList<Capital> result = new ArrayList<Capital>();
                              
                               Iterator<Capital> iterator = getCapitals().iterator();
                               while (iterator.hasNext()) {
                               Capital elem = ((Capital) iterator.next());
                               if ((elem.getName() != null && elem.getName().toLowerCase().indexOf(pref.toLowerCase()) == 0) || "".equals(pref))
                               {
                               result.add(elem);
                               }
                               }
                               return result;
                               }
                              
                               public CapitalsBean() {
                               URL rulesUrl = getClass().getResource("capitals-rules.xml");
                               Digester digester = DigesterLoader.createDigester(rulesUrl);
                               digester.push(this);
                               try {
                               digester.parse(getClass().getResourceAsStream("capitals.xml"));
                               } catch (IOException e) {
                               throw new FacesException(e);
                               } catch (SAXException e) {
                               throw new FacesException(e);
                               }
                               capitalsNames.clear();
                               for (Capital cap : capitals) {
                               capitalsNames.add(cap.getName());
                               }
                               capitalsOptions.clear();
                               for (Capital cap : capitals) {
                               capitalsOptions.add(new SelectItem(cap.getName(),cap.getState()));
                               }
                               }
                              
                               public void resetFilter() {
                               setCurrentNameFilterValue("");
                               setCurrentStateFilterValue("");
                               }
                              
                               public String addCapital(Capital capital) {
                               capitals.add(capital);
                               return null;
                               }
                              
                               public ArrayList<Capital> getCapitals() {
                               return capitals;
                               }
                              
                               public String getCapital() {
                               return capital;
                               }
                              
                               public void setCapital(String capital) {
                               this.capital = capital;
                               }
                              
                               public List<SelectItem> getCapitalsOptions() {
                               return capitalsOptions;
                               }
                              
                               public ArrayList<String> getCapitalsNames() {
                               return capitalsNames;
                               }
                              
                               public String getCurrentStateFilterValue() {
                               return currentStateFilterValue;
                               }
                              
                               public void setCurrentStateFilterValue(String currentStateFilterValue) {
                               this.currentStateFilterValue = currentStateFilterValue;
                               }
                              
                               public String getCurrentNameFilterValue() {
                               return currentNameFilterValue;
                               }
                              
                               public void setCurrentNameFilterValue(String currentNameFilterValue) {
                               this.currentNameFilterValue = currentNameFilterValue;
                               }
                              
                              }
                              


                              • 12. Re: Clearing builtin filtering/sorting in rich:datatable
                                smonty1

                                Hi Ilya,
                                I saw your JIRA article at http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4246607#4246607. Thanks again for your quick response.

                                Unfortunately I'm still seeing the same behaviour of the filter input fields not reflecting what the backing bean filter field value is ie no field update. Semantically the code example you used was what I was using but I decided to go back to first principles as well and pare down the (unneeded) options:

                                1. I removed the enveloping a4j:outputPanel and rich:simpleTogglePanel tags so datatable was on it's own.
                                2. Moved up one of the filter fields into the reconciliationTable bean in case it was some sort of Java reference thing.
                                3. Added lots of debug logging ie on filter field values setters/getters and on reset functions.
                                4. Created additonal new a4j:commandButton within the table's enclosing form tags - identical options to your own example (apart from the action value of course).
                                5. Removed sorting options from the filter columns and other misc options from table/columns.

                                The only differences that I can see between our implementations are that I don't use the ui:composition tags and my view/jsp is constructed from subviews (each subview has it's own jsp). I don't think this matters though...?

                                I'm using IBM WASCE 2.0 (with MyFaces 1.2.6 jars added to WEB-INF/lib + inverse classloading) and RichFaces 3.3.1_GA. WASCE 2.0 comes with MyFaces 1.2.0 and so I added MyFaces 1.2.6 jars (latest at time of addition) to insure it meets RichFaces 3.3.1 software requirements.

                                If it helps, I might try to create a cut down WAR for you.

                                Thanks,
                                Stephen

                                • 13. Re: Clearing builtin filtering/sorting in rich:datatable
                                  ilya_shaikovsky

                                  yes, please share the war.. please make sure it not required datasource but mock data based and specify container to be used for deploy. Then the review will be much faster.

                                  • 14. Re: Clearing builtin filtering/sorting in rich:datatable
                                    smonty1

                                    Hi Ilya,
                                    I did some further investigation and have created a WAR for you. I basically bundled up your supplied Capitals demo code and tested against WASCE 2.0 and the latest WASCE 2.1 version. Both showed the same characteristics ie clicking the reset button returned all of the unfiltered population but did NOT clear the filter fields.
                                    I have sent you an email with the attached WAR.

                                    Thanks,
                                    Stephen

                                    1 2 Previous Next