Primefaces selectCheckboxMenu过滤器不能正常工作,而selectOneMenu在数据表中

Kor*_*kig 5 datatable jsf primefaces

我有一个Primefaces(5.0)数据表.我使用两个列过滤器:selectOneMenu(Filter1)和selectCheckboxMenu(Filter2).

两个过滤器的数据都被正确填充.selectOneMenu(Filter1)可以过滤DataTable,但selectCheckboxMenu(Filter2)在选择值后没有找到任何数据.

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>
Run Code Online (Sandbox Code Playgroud)

dropdowns.trucksWithAllOption

在此输入图像描述

渲染过滤器1

在此输入图像描述

渲染Filter2

在此输入图像描述

为什么selectCheckboxMenu(Filter2)找不到任何数据而selectOneMenu(Filter1)找不到相同的数据?

小智 6

我知道这可能是个老问题,但我现在一直在努力使用selectCheckboxMenu过滤器,我终于找到了解决方案.首先,您应该在代码中执行以下操作以使此过滤器起作用:

  • filterBy设置为您在outputText中显示的确切值
  • String []值,用于在bean中存储选定的过滤器值
  • 捕获更改并使用ajax选择所有复选框事件并触发PrimeFaces过滤器功能
  • 绑定bean中的侦听器以在selectCheckboxMenu触发时处理过滤器事件
  • 为了避免javascript版本的问题,只需将表ID和widgetVar设置为相同的值(在我们的示例"TABLEID"中)
  • 在UI组件中设置ID,并在数据表中找出此列的索引.最好是将这两个设置为控制器或演示者中的常量

    <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}"/>
    
    Run Code Online (Sandbox Code Playgroud)

在bean中,您需要实现侦听器.您还需要实现将实际FilterMeta对象加载到属于datatable对象的FilterMetadata对象的方法.由于PrimeFaces没有为String数组选择值过滤器传递好的值,我们基本上将在我们的bean中连接这个数组,然后将它转换为PrimeFaces没有提供的FilterMeta对象.所以将以下代码添加到您的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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)