Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Primefaces selectCheckboxMenu filter doesn't work while selectOneMenu well inside datatable

I have a Primefaces(5.0) datatable. I use two column filters: selectOneMenu(Filter1) and selectCheckboxMenu(Filter2).

Both filter's data are being filled fine. selectOneMenu(Filter1) can filter the DataTable but the selectCheckboxMenu(Filter2) finds no any data after selecting a value.

JSF

<p:dataTable value="#{employeeBean.employees}" var="employee" id="employeeDTable"
    emptyMessage="No data" filteredValue="#{employeeBean.filteredEmployees}"
    widgetVar="empWidgetVar" rowKey="#{employee.id}">
    
    <!-- THIS WORKS -->
    <p:column headerText="Filter1" filterBy="truck.id" filterMatchMode="exact">
        <f:facet name="filter">
            <p:selectOneMenu onchange="PF('empWidgetVar').filter()">
                <f:selectItems value="#{dropdowns.trucksWithAllOption}"/>
            </p:selectOneMenu>
        </f:facet>
        <h:outputText value="#{employee.truck.license}"/>
    </p:column>
    
    <!-- THIS DOESN'T WORK (Doesn't find any data) -->
    <p:column headerText="Filter2" filterBy="truck.id" filterMatchMode="in">
        <f:facet name="filter">
            <p:selectCheckboxMenu onchange="PF('empWidgetVar').filter()" label="Vrachtwagen">
                <f:selectItems value="#{dropdowns.trucksWithAllOption}"/>
            </p:selectCheckboxMenu>
        </f:facet>
        <h:outputText value="#{employee.truck.license}"/>
    </p:column>
    
</p:dataTable>

dropdowns.trucksWithAllOption

enter image description here

Rendered Filter1

enter image description here

Rendered Filter2

enter image description here

Why selectCheckboxMenu(Filter2) can't find any data while selectOneMenu(Filter1) finds well with the same data?

like image 944
Korki Korkig Avatar asked May 19 '14 18:05

Korki Korkig


1 Answers

I know this might be an old question, but I've been struggling with selectCheckboxMenu Filter for days now, and I finally found a solution. First of all, there are several things you should do in your code to get this filter to work:

  • filterBy set to the exact value that you are displaying in outputText
  • String[] value to store your selected filter values in your bean
  • catch change and selectAll checkbox events with ajax and trigger the PrimeFaces filter function
  • bind a listener in your bean to handle the filter events when triggered by selectCheckboxMenu
  • to avoid problems with javascript versions, just set both your table ID and widgetVar to the same value (in our example "TABLEID")
  • Set ID in your UI component and figure out the index of this column in the datatable. Best is to set these two as constants in your controller or presenter

    <p:column id="columnLicenses" headerText="Filter2" filterBy="employee.truck.license" filterMatchMode="in">
    <f:facet name="filter">
        <p:selectCheckboxMenu value="#{employeeBean.selectedTrucks}" label="Vrachtwagen">
            <f:selectItems value="#{dropdowns.trucksWithAllOption}"/>
            <p:ajax event="change" process="@this" update=":FORMID" listener="#{employeeBean.onFilter()}" oncomplete="PF('TABLEID').filter()" />
            <p:ajax event="toggleSelect" process="@this" update=":FORMID" listener="#{employeeBean.onFilter()}" oncomplete="PF('TABLEID').filter()" />
        </p:selectCheckboxMenu>
    </f:facet>
    <h:outputText value="#{employee.truck.license}"/>
    

In your bean, you need to implement the listener. Also you need to implement the method that is going to load your actual FilterMeta object into the FilterMetadata object, that belongs to the datatable object. Since PrimeFaces does not pass the good value for String array selection value filter, we are basically going to wire this array in our bean, and then convert it to the FilterMeta object that PrimeFaces did not deliver. So add following code to your bean:

private static final String TABLE_ID = "TABLEID";
private static final String COLUMN_ID_LICENSES = "columnLicenses";
private static final int COLUMN_INDEX_LICENSES = 2; // for example, it is third column in the table
private String [] selectedTrucks; // Also generate getter and setter for this

public void onFilter() {
        DataTable table = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent(TABLE_ID);
        updateCollectionFilterFor(table, COLUMN_ID_LICENSES, selectedTrucks,
                COLUMN_INDEX_LICENSES);
    }

@SuppressWarnings("unchecked")
private void updateCollectionFilterFor(final DataTable table, final String columnId, final String[] filterValue,
        int columnIndex) {
    for (UIColumn column : table.getColumns()) {
        if (column.getClientId().contains(columnId)) {
            ValueExpression columnFilterByVE = column.getValueExpression("filterBy");
            if (null != columnFilterByVE) {
                FilterMeta fm = new FilterMeta(column, columnFilterByVE, filterValue);
                table.getFilterMetadata().remove(columnIndex);
                table.getFilterMetadata().add(columnIndex, fm);
            }
        }
    }
}
like image 122
Vanja Lee Avatar answered Oct 22 '22 13:10

Vanja Lee