Primefaces 5 Checkbox过滤后多选错误

时间:2014-08-06 09:54:03

标签: primefaces datatable multi-select

我在Wildfly 8.0.0上使用Primefaces 5和Primefaces Extension 2.0.0以及JSF 2.2。

我使用freezeColumns,过滤,分页以及内置复选框提供的多选来实现数据表。

在大多数情况下,会提交所选项目,但不会在以下示例中提交:

  1. 未选择任何项目
  2. 使用任何过滤器字段过滤数据表内容
  3. 选择项目
  4. 提交表格 - >没有选定的项目被提交
  5. the primefaces Forum

    中提供的图片

    我的数据表的xhtml

    <h:form id="jobListForm">
        <p:panelGrid columns="2" styleClass="no-border">
        </p:panelGrid>
        <p:panelGrid columns="2" styleClass="no-border">
            <p:selectBooleanCheckbox id="showAllTenants" value="#{JobProtocolBean.showAllTenants}" rendered="#{TenantController.isSuperAdmin}">
                <p:ajax listener="#{FacesController.refresh}" event="change"/>
            </p:selectBooleanCheckbox>
            <p:outputLabel for="showAllTenants" value="Show all tenants" rendered="#{TenantController.isSuperAdmin}"/>
        </p:panelGrid>
        <h:panelGroup>
            <mx:tableControls managedBean="#{JobProtocolBean}" />
            <p:commandButton icon="ui-icon-arrowreturnthick-1-s" action="#{JobProtocolBean.showExportDialog}" value="Export" ajax="false" rendered="#{Shiro.isPermitted('jobprotocol:list:xmlexport')}" />
            <p:dataTable id="JobProtocolTable" widgetVar="JobProtocolTableVar" value="#{JobProtocolBean.items}" binding="#{JobProtocolBean.items.dataTable}" lazy="true" 
                    filteredValue="#{JobProtocolBean.filter}" var="item" paginator="true" rows="10"
                    currentPageReportTemplate="(Displaying results {startRecord} - {endRecord} of {totalRecords})" 
                    paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                    rowsPerPageTemplate="10,20,50,100,200,500,1000" filterEvent="enter"
                    selection="#{JobProtocolBean.selectedJobProtocols}"
                    scrollable="true" scrollWidth="50%" scrollHeight="100%" frozenColumns="2">
                <f:event type="preRenderComponent" listener="#{JobProtocolBean.items.preRenderComponent}" />
    <p:column id="ACTIONS" headerText="Actions" width="120">
                    <p:panelGrid columns="4" styleClass="button-column">
                        <p:commandButton icon="ui-icon-info" action="#{JobProtocolBean.startDetail}" ajax="false" title="Detail" disabled="#{not Shiro.isPermitted('jobprotocol:list:detail')}"/>
                        <p:commandButton icon="ui-icon-pencil" action="#{JobProtocolBean.startEdit}" ajax="false" title="Edit" disabled="#{not (Shiro.isPermitted('jobprotocol:list:edit') and (item.stateSkipped or item.stateUnplanned))}" />
                        <p:commandButton icon="ui-icon-copy" action="#{JobProtocolBean.startCopy}" ajax="false" title="Copy" disabled="#{not (Shiro.isPermitted('jobprotocol:list:retry') and item.stateDone and item.cron eq 'onetime')}" rendered="#{item.stateDone}" />
                        <p:commandButton icon="ui-icon-arrowrefresh-1-e" action="#{JobProtocolBean.startRetry}" ajax="false" title="Retry" disabled="#{not (Shiro.isPermitted('jobprotocol:list:retry') and item.stateSkipped)}" rendered="#{not (item.stateDone or item.stateQueued or item.stateUnplanned or item.statePlanned)}" />
                        <p:commandButton icon="ui-icon-pause" action="#{JobProtocolBean.startSuspend}" ajax="false" title="Suspend" onclick="return confirm('Do you really want to suspend this job?');" disabled="#{not Shiro.isPermitted('jobprotocol:list:suspend')}" rendered="#{item.statePlanned}" />
                        <p:commandButton icon="ui-icon-play" action="#{JobProtocolBean.startResume}" ajax="false" title="Resume" onclick="return confirm('Do you really want to resume this job?');" disabled="#{not Shiro.isPermitted('jobprotocol:list:resume')}" rendered="#{item.stateUnplanned}" />
                        <p:commandButton icon="ui-icon-circle-minus" action="#{JobProtocolBean.startUnqueue}" ajax="false" title="Unqueue" onclick="return confirm('Do you really want to unqueue and re-schedule this job?');" disabled="#{not Shiro.isPermitted('jobprotocol:list:unqueue')}" rendered="#{item.stateQueued}" />
                        <p:commandButton icon="ui-icon-cancel" action="#{JobProtocolBean.startSkip}" ajax="false" title="Skip" disabled="#{not Shiro.isPermitted('jobprotocol:list:skip') or item.stateDoneOrSkipped}" />
                    </p:panelGrid>
                </p:column>
    
                <p:column selectionMode="multiple" width="18" />
    
                <p:column id="ID" headerText="ID" sortBy="#{item.id}" filterBy="#{item.id}" width="50">
                    <h:outputText title="#{item.id}" value="#{item.id}"/>
                </p:column>
    
                <p:column id="TENANT" headerText="Tenant" rendered="#{JobProtocolBean.showAllTenants}" sortBy="#{item.tenantId}" filterBy="#{item.tenantId}" width="50">
                    <h:outputText title="#{item.tenantId}" value="#{item.tenantId}" converter="JobTenantConverter"/>
                </p:column>
    
                <p:column id="INITIATOR" headerText="Initiator" sortBy="#{item.initiator}" filterBy="#{item.initiator}" width="120">
                    <h:outputText title="#{item.initiator}" value="#{item.initiator}" />
                </p:column>
    
                <p:column id="CODE" headerText="Code" sortBy="#{item.code}" filterBy="#{item.code}" width="300">
                    <h:outputText title="#{item.code}" value="#{item.code}" converter="JobCodeConverter" escape="false" />
                </p:column>
    
                <p:column id="CHANNEL_ID" headerText="Channel ID" sortBy="#{item.channelId}" filterBy="#{item.channelId}" width="150">
                    <h:outputText title="#{item.channel}" value="#{item.channel}"  />
                </p:column>
    
                <p:column id="SEQUENCE" headerText="Sequence" sortBy="#{item.orderId}" filterBy="#{item.orderId}" width="65" >
                    <h:outputText title="#{item.orderId}" value="#{item.orderId}" />
                </p:column>
    
                <p:column id="STATE" headerText="State" filterBy="#{item.state}" filterOptions="#{JobProtocolBean.states}" width="80">
                    <h:outputText value="#{item}" converter="JobStateConverter" />
                </p:column>
    
                <p:column id="CRON" headerText="Cron" sortBy="#{item.cron}" filterBy="#{item.cron}" width="70" >
                    <h:outputText title="#{item.cron}" value="#{item.cron}" />
                </p:column>
    
                <p:column id="META" headerText="Meta" sortBy="#{item.meta}" filterBy="#{item.meta}" width="100">
                    <h:outputText title="#{item.meta}" value="#{item.meta}" />
                </p:column>
    
                <p:column id="MIN_FAILURES" headerText="&#8805; Retries" sortBy="#{item.failures}" filterBy="#{item.failures}" width="60">
                    <h:outputText title="#{item.failures}" value="#{item.failures}" />
                </p:column>
    
                <p:column id="BUSINESS_ERROR" headerText="Failure" sortBy="#{item.errorCode}" filterBy="#{item.errorCode}" width="80">
                    <h:outputText title="#{item.errorCode}" value="#{item.errorCode}" />
                </p:column>
    
                <p:column id="SKIP_REASON" headerText="Skip Reason" sortBy="#{item.skipReason}" filterBy="#{item.skipReason}" width="80">
                    <h:outputText title="#{item.skipReason}" value="#{item.skipReason}" />
                </p:column>
    
                <p:column id="TIME_STORED" sortBy="#{item.timeStored}" width="120">
                    <mxtaglib:dateFilter dateProperty="#{item.timeStored}" datePropertyName="timeStored" headerText="Time Stored" tableBinding="#{JobProtocolBean.items}"/>
                </p:column>
    
                <p:column id="PLANNED_START" sortBy="#{item.nextPlannedStart}" width="120">
                    <mxtaglib:dateFilter dateProperty="#{item.nextPlannedStart}" datePropertyName="nextPlannedStart" headerText="Planned Start" tableBinding="#{JobProtocolBean.items}"/>
                </p:column>
    
                <p:column id="TIME_QUEUED" sortBy="#{item.timeQueued}" width="120">
                    <mxtaglib:dateFilter dateProperty="#{item.timeQueued}" datePropertyName="timeQueued" headerText="Time Queued" tableBinding="#{JobProtocolBean.items}"/>
                </p:column>
    
                <p:column id="TIME_STARTED" sortBy="#{item.timeStarted}" width="120">
                    <mxtaglib:dateFilter dateProperty="#{item.timeStarted}" datePropertyName="timeStarted" headerText="Time Started" tableBinding="#{JobProtocolBean.items}"/>
                </p:column>
    
                <p:column id="TIME_DONE" sortBy="#{item.timeDone}" width="120">
                    <mxtaglib:dateFilter dateProperty="#{item.timeDone}" datePropertyName="timeDone" headerText="Time Done" tableBinding="#{JobProtocolBean.items}"/>
                </p:column>
            </p:dataTable>
            <p:outputPanel styleClass="ui-paginator-inline-span">
                <p:selectOneMenu id="ACTION_SELECTOR" value="#{JobProtocolBean.selectedAction}" >
                    <f:selectItems value="#{JobProtocolBean.accessibleActions}" itemValue="#{JobProtocolBean.accessibleActions.value}" />
                </p:selectOneMenu>  
                <p:commandButton id="ACTION_BUTTON" action="#{JobProtocolBean.startActionSelected}" ajax="false" value="OK" />
            </p:outputPanel>
                  <mxtaglib:blockUI block="JobProtocolTable" trigger="JobProtocolTable" styleClass="block-ui" />
        </h:panelGroup>
    </h:form>
    

    <h:form id="jobListForm"> <p:panelGrid columns="2" styleClass="no-border"> </p:panelGrid> <p:panelGrid columns="2" styleClass="no-border"> <p:selectBooleanCheckbox id="showAllTenants" value="#{JobProtocolBean.showAllTenants}" rendered="#{TenantController.isSuperAdmin}"> <p:ajax listener="#{FacesController.refresh}" event="change"/> </p:selectBooleanCheckbox> <p:outputLabel for="showAllTenants" value="Show all tenants" rendered="#{TenantController.isSuperAdmin}"/> </p:panelGrid> <h:panelGroup> <mx:tableControls managedBean="#{JobProtocolBean}" /> <p:commandButton icon="ui-icon-arrowreturnthick-1-s" action="#{JobProtocolBean.showExportDialog}" value="Export" ajax="false" rendered="#{Shiro.isPermitted('jobprotocol:list:xmlexport')}" /> <p:dataTable id="JobProtocolTable" widgetVar="JobProtocolTableVar" value="#{JobProtocolBean.items}" binding="#{JobProtocolBean.items.dataTable}" lazy="true" filteredValue="#{JobProtocolBean.filter}" var="item" paginator="true" rows="10" currentPageReportTemplate="(Displaying results {startRecord} - {endRecord} of {totalRecords})" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" rowsPerPageTemplate="10,20,50,100,200,500,1000" filterEvent="enter" selection="#{JobProtocolBean.selectedJobProtocols}" scrollable="true" scrollWidth="50%" scrollHeight="100%" frozenColumns="2"> <f:event type="preRenderComponent" listener="#{JobProtocolBean.items.preRenderComponent}" /> <p:column id="ACTIONS" headerText="Actions" width="120"> <p:panelGrid columns="4" styleClass="button-column"> <p:commandButton icon="ui-icon-info" action="#{JobProtocolBean.startDetail}" ajax="false" title="Detail" disabled="#{not Shiro.isPermitted('jobprotocol:list:detail')}"/> <p:commandButton icon="ui-icon-pencil" action="#{JobProtocolBean.startEdit}" ajax="false" title="Edit" disabled="#{not (Shiro.isPermitted('jobprotocol:list:edit') and (item.stateSkipped or item.stateUnplanned))}" /> <p:commandButton icon="ui-icon-copy" action="#{JobProtocolBean.startCopy}" ajax="false" title="Copy" disabled="#{not (Shiro.isPermitted('jobprotocol:list:retry') and item.stateDone and item.cron eq 'onetime')}" rendered="#{item.stateDone}" /> <p:commandButton icon="ui-icon-arrowrefresh-1-e" action="#{JobProtocolBean.startRetry}" ajax="false" title="Retry" disabled="#{not (Shiro.isPermitted('jobprotocol:list:retry') and item.stateSkipped)}" rendered="#{not (item.stateDone or item.stateQueued or item.stateUnplanned or item.statePlanned)}" /> <p:commandButton icon="ui-icon-pause" action="#{JobProtocolBean.startSuspend}" ajax="false" title="Suspend" onclick="return confirm('Do you really want to suspend this job?');" disabled="#{not Shiro.isPermitted('jobprotocol:list:suspend')}" rendered="#{item.statePlanned}" /> <p:commandButton icon="ui-icon-play" action="#{JobProtocolBean.startResume}" ajax="false" title="Resume" onclick="return confirm('Do you really want to resume this job?');" disabled="#{not Shiro.isPermitted('jobprotocol:list:resume')}" rendered="#{item.stateUnplanned}" /> <p:commandButton icon="ui-icon-circle-minus" action="#{JobProtocolBean.startUnqueue}" ajax="false" title="Unqueue" onclick="return confirm('Do you really want to unqueue and re-schedule this job?');" disabled="#{not Shiro.isPermitted('jobprotocol:list:unqueue')}" rendered="#{item.stateQueued}" /> <p:commandButton icon="ui-icon-cancel" action="#{JobProtocolBean.startSkip}" ajax="false" title="Skip" disabled="#{not Shiro.isPermitted('jobprotocol:list:skip') or item.stateDoneOrSkipped}" /> </p:panelGrid> </p:column> <p:column selectionMode="multiple" width="18" /> <p:column id="ID" headerText="ID" sortBy="#{item.id}" filterBy="#{item.id}" width="50"> <h:outputText title="#{item.id}" value="#{item.id}"/> </p:column> <p:column id="TENANT" headerText="Tenant" rendered="#{JobProtocolBean.showAllTenants}" sortBy="#{item.tenantId}" filterBy="#{item.tenantId}" width="50"> <h:outputText title="#{item.tenantId}" value="#{item.tenantId}" converter="JobTenantConverter"/> </p:column> <p:column id="INITIATOR" headerText="Initiator" sortBy="#{item.initiator}" filterBy="#{item.initiator}" width="120"> <h:outputText title="#{item.initiator}" value="#{item.initiator}" /> </p:column> <p:column id="CODE" headerText="Code" sortBy="#{item.code}" filterBy="#{item.code}" width="300"> <h:outputText title="#{item.code}" value="#{item.code}" converter="JobCodeConverter" escape="false" /> </p:column> <p:column id="CHANNEL_ID" headerText="Channel ID" sortBy="#{item.channelId}" filterBy="#{item.channelId}" width="150"> <h:outputText title="#{item.channel}" value="#{item.channel}" /> </p:column> <p:column id="SEQUENCE" headerText="Sequence" sortBy="#{item.orderId}" filterBy="#{item.orderId}" width="65" > <h:outputText title="#{item.orderId}" value="#{item.orderId}" /> </p:column> <p:column id="STATE" headerText="State" filterBy="#{item.state}" filterOptions="#{JobProtocolBean.states}" width="80"> <h:outputText value="#{item}" converter="JobStateConverter" /> </p:column> <p:column id="CRON" headerText="Cron" sortBy="#{item.cron}" filterBy="#{item.cron}" width="70" > <h:outputText title="#{item.cron}" value="#{item.cron}" /> </p:column> <p:column id="META" headerText="Meta" sortBy="#{item.meta}" filterBy="#{item.meta}" width="100"> <h:outputText title="#{item.meta}" value="#{item.meta}" /> </p:column> <p:column id="MIN_FAILURES" headerText="&#8805; Retries" sortBy="#{item.failures}" filterBy="#{item.failures}" width="60"> <h:outputText title="#{item.failures}" value="#{item.failures}" /> </p:column> <p:column id="BUSINESS_ERROR" headerText="Failure" sortBy="#{item.errorCode}" filterBy="#{item.errorCode}" width="80"> <h:outputText title="#{item.errorCode}" value="#{item.errorCode}" /> </p:column> <p:column id="SKIP_REASON" headerText="Skip Reason" sortBy="#{item.skipReason}" filterBy="#{item.skipReason}" width="80"> <h:outputText title="#{item.skipReason}" value="#{item.skipReason}" /> </p:column> <p:column id="TIME_STORED" sortBy="#{item.timeStored}" width="120"> <mxtaglib:dateFilter dateProperty="#{item.timeStored}" datePropertyName="timeStored" headerText="Time Stored" tableBinding="#{JobProtocolBean.items}"/> </p:column> <p:column id="PLANNED_START" sortBy="#{item.nextPlannedStart}" width="120"> <mxtaglib:dateFilter dateProperty="#{item.nextPlannedStart}" datePropertyName="nextPlannedStart" headerText="Planned Start" tableBinding="#{JobProtocolBean.items}"/> </p:column> <p:column id="TIME_QUEUED" sortBy="#{item.timeQueued}" width="120"> <mxtaglib:dateFilter dateProperty="#{item.timeQueued}" datePropertyName="timeQueued" headerText="Time Queued" tableBinding="#{JobProtocolBean.items}"/> </p:column> <p:column id="TIME_STARTED" sortBy="#{item.timeStarted}" width="120"> <mxtaglib:dateFilter dateProperty="#{item.timeStarted}" datePropertyName="timeStarted" headerText="Time Started" tableBinding="#{JobProtocolBean.items}"/> </p:column> <p:column id="TIME_DONE" sortBy="#{item.timeDone}" width="120"> <mxtaglib:dateFilter dateProperty="#{item.timeDone}" datePropertyName="timeDone" headerText="Time Done" tableBinding="#{JobProtocolBean.items}"/> </p:column> </p:dataTable> <p:outputPanel styleClass="ui-paginator-inline-span"> <p:selectOneMenu id="ACTION_SELECTOR" value="#{JobProtocolBean.selectedAction}" > <f:selectItems value="#{JobProtocolBean.accessibleActions}" itemValue="#{JobProtocolBean.accessibleActions.value}" /> </p:selectOneMenu> <p:commandButton id="ACTION_BUTTON" action="#{JobProtocolBean.startActionSelected}" ajax="false" value="OK" /> </p:outputPanel> <mxtaglib:blockUI block="JobProtocolTable" trigger="JobProtocolTable" styleClass="block-ui" /> </h:panelGroup> </h:form>

1 个答案:

答案 0 :(得分:0)

我找到了所描述错误的起源: 带有frozenColumns的数据表的Javascript对象提供了一个函数来复制ajax请求所带来的,如sort,filter等。 此函数不处理保存在数据(jQuery data())中的'rk'值。

原件:

copyRow: function(original) {
    return $('<tr></tr>').data('ri', original.data('ri')).addClass(original.attr('class')).attr('role', 'row');
};

我的解决方法:

PF(datatableUtils.datatableWidgetVar).copyRow = function(original) {
    return $('<tr></tr>').attr('data-ri', original.data('ri')).attr('data-rk', original.data('rk')).addClass(original.attr('class')).attr('role', 'row');
};

使用attr()和'data-'前缀写入数据是必要的,因为它似乎丢失了存储的数据,因为tr尚未附加。 (老实说,如果我错了,请纠正我)