Skip to content

‘Show All’ button for Primefaces DataTable

I would like to have a ‘Show All’ button for a primefaces datatable, however, I’m experiencing some trouble. Here’s some test code that demostrates the problem:

Test.xhtml:

          ...  
            <h:form>
                <p:selectBooleanCheckbox value="#{testBean.showAll}" itemLabel="Show All">
                    <p:ajax update="@form"/> 
                </p:selectBooleanCheckbox>

                <p:panel id="test">
                    <p:dataTable id="values" var="value" value="#{testBean.fullList}" filteredValue="#{testBean.filteredList}" paginatorAlwaysVisible="false" 
                                 paginator="#{!testBean.showAll}" rows="#{!testBean.showAll ? 2 : null }" widgetVar="valuesTable"
                                 emptyMessage="No records found.">


                        <p:column id="enum" sortBy="#{value.toString()}" filterBy="#{value.toString()}" filterMatchMode="contains">
                            <f:facet name="header">
                                <h:outputText value="Enum" />
                            </f:facet>
                            <h:outputText value ="#{value.toString()}"/>
                        </p:column>
                        <p:column id="name" sortBy="#{value.name}"  filterBy="#{value.name}" filterMatchMode="contains">
                            <f:facet name="header">
                                <h:outputText value="Name" />
                            </f:facet>
                            <h:outputText value="#{value.name}" />
                        </p:column>
                    </p:dataTable>
                </p:panel>
            </h:form>
          ...

And here’s TestBean.java:

import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

@Named(value = "testBean")
@SessionScoped
public class TestBean implements Serializable {

    public static enum Value {

        ONE, TWO, THREE;

        public String getName() {
            return name().toLowerCase();
        }

        @Override
        public String toString() {
            return this.name();
        }
    }

    /**
     * Creates a new instance of TestBean
     */
    public TestBean() {
    }

    private boolean showAll = false;
    private List<Value> fullList = Arrays.asList(Value.values());
    private List<Value> filteredList;

    public boolean isShowAll() {
        return showAll;
    }

    public void setShowAll(boolean showAll) {
        this.showAll = showAll;
    }

    public List<Value> getFullList() {
        return fullList;
    }

    public void setFullList(List<Value> fullList) {
        this.fullList = fullList;
    }

    public List<Value> getFilteredList() {
        return filteredList;
    }

    public void setFilteredList(List<Value> filteredList) {
        this.filteredList = filteredList;
    }

}

If I don’t change tabs, the page works as expected: toggling the ‘Show All’ button updates the table to show all 3 values, or only two. However, if show all is not checked (only 2 rows are showing), and I click to the 2nd page of the table to view the third record, and then click ‘Show All’, the table does not update properly. It removes the paginator from the top of the table (as expected), but still only shows the 3rd record. And if I then uncheck show all and navigate back to the first page of the datatable, it is now broken too.

I’ve tried changing the ajax update statement to the id of the table, but that didn’t change the results.

Am I doing something wrong? Thanks in advance.

Answer

You have to programmatically set the values you need directly on the DataTable component (I used explicit first and rows bean properties just for more readability):

<h:form>
    <p:selectBooleanCheckbox value="#{testBean.showAll}" itemLabel="Show All">
        <p:ajax update="@form" />
    </p:selectBooleanCheckbox>

    <p:panel id="test">
        <p:dataTable id="values" var="value" value="#{testBean.fullList}"
            filteredValue="#{testBean.filteredList}" paginatorAlwaysVisible="false"
            paginator="#{!testBean.showAll}" first="#{testBean.first}" rows="#{testBean.rows}"
            widgetVar="valuesTable" emptyMessage="No records found.">


            <p:column id="enum" sortBy="#{value.toString()}" filterBy="#{value.toString()}"
                filterMatchMode="contains">
                <f:facet name="header">
                    <h:outputText value="Enum" />
                </f:facet>
                <h:outputText value="#{value.toString()}" />
            </p:column>
            <p:column id="name" sortBy="#{value.name}" filterBy="#{value.name}"
                filterMatchMode="contains">
                <f:facet name="header">
                    <h:outputText value="Name" />
                </f:facet>
                <h:outputText value="#{value.name}" />
            </p:column>
        </p:dataTable>
    </p:panel>
</h:form>

and

@Named
@ViewScoped
public class TestBean implements Serializable
{
    private static final long serialVersionUID = 1L;

    public static enum Value
    {
        ONE, TWO, THREE;

        public String getName()
        {
            return name().toLowerCase();
        }

        @Override
        public String toString()
        {
            return name();
        }
    }

    private boolean showAll = false;
    private int first = 0;
    private int rows = 2;
    private List<Value> fullList = Arrays.asList(Value.values());
    private List<Value> filteredList;

    public boolean isShowAll()
    {
        return showAll;
    }

    public void setShowAll(boolean showAll)
    {
        this.showAll = showAll;
        first = 0;
        rows = showAll ? 0 : 2;
        filteredList = null;

        // get the FacesContext instance
        FacesContext context = FacesContext.getCurrentInstance();

        // get the current component (p:selectBooleanCheckbox)
        UIComponent component = UIComponent.getCurrentComponent(context);

        // find DataTable within the same NamingContainer
        DataTable table = (DataTable) component.findComponent("values");

        // reset first row index
        table.setFirst(first);

        // reset last row index
        table.setRows(rows);

        // reset filterd value
        table.setFilteredValue(null);
    }

    // all other getters/setters
}

Tested on Wildfly 10.0.0.Final with JSF 2.3.0-m06 (Mojarra) and PrimeFaces 6.0.2