如何对所有选项卡 primefaces 使用相同的数据表(在这种情况下调整大小不起作用)

How to use the same datatable for all the tabs primefaces (resize not working in this case)

我正在使用 primefaces 5.3 和 jsf 2.2.6。

我创建了两个静态选项卡,看看它是否可以使用包含数据表的相同 xhtml 页面 (transactionsPage)。

这些是选项卡:

    <h:form id="formTabs">
      <p:tabView id="tabs" activeIndex="#{mainPage.index}">
        <p:ajax event="tabClose" listener="#{mainPage.remove}" update="formTabs" />
        <p:ajax event="tabChange" listener="#{mainPage.changeTab}" update="formTabs" />
            <p:tab id="transAssembling" title="ASSEMBLING" closable="true">
                <f:subview id="tab0">   
                    <ui:include src="transactionsPage.xhtml">
                        <ui:param name="status" value="ASSEMBLING" />
                        <ui:param name="columnList" value="#{tabs.list[0].columnList}" />
                    </ui:include>
                </f:subview>
            </p:tab>

            <p:tab id="transPrinting" title="PRINTING" closable="true">
                <f:subview id="tab1">
                    <ui:include src="transactionsPage.xhtml">
                        <ui:param name="status" value="PRINTING" />
                        <ui:param name="columnList" value="#{tabs.list[1].columnList}" />
                    </ui:include>
                </f:subview>
            </p:tab>
     </p:tabView>
</h:form>

我使用了子视图,以便从包含的 transactionsPage.xhtml 中获得不同的数据表 ID,这样我就可以对所有选项卡使用相同的 xhtml 页面,并且只更改列和数据,即在transactionsPage.xhtml.

的托管bean中计算

所以对于数据表 从第一个选项卡开始:绝对路径为

formTabs:tabs:tab0:transactionsTable

从第二个选项卡:绝对路径是

formTabs:tabs:tab1:transactionsTable

这是来自交易页面的数据表:

<p:dataTable id="transactionsTable" var="data" value="#{transactionsPage.ttList}" widgetVar="projectData" 
                     rowKey="#{data.id}"
                     draggableColumns="true" 
                     draggableRows="true"
                     resizableColumns="true" emptyMessage="#{msg['form.noTransactionsFound']}" rows="20"
                     selectionMode="single" selection="#{transactionsPage.selectedTransaction}"
                     filteredValue="#{transactionsPage.fitleredttList}" paginator="true" paginatorPosition="both" paginatorTemplate="{CurrentPageReport} {RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}"
                     >

            <p:ajax event="colResize" listener="#{transactionsPage.onColumnResize}" update="transactionsTable"/>

            <f:ajax event="rowSelect" render="formTabs"/>
            <!-- Stiky does not work with column filtering paginator="true" paginatorPosition="bottom" paginatorTemplate="{CurrentPageReport} {RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} " stickyHeader="true" -->

            <f:facet name="header">
                <p:outputPanel styleClass="mainPageProjectsTableHeader" >
                    <h:outputText value="#{msg['form.searchAllFields']}" style="float:left; margin-right:10px;"/>
                    <p:inputText id="globalFilter" onkeyup="PF('projectData').filter()" style="width:150px; float:left" placeholder=" #{msg['form.enterKeyword']}"/>

                    <p:commandButton id="toggler" type="button" value="#{msg['form.columns']}" 
                            styleClass="columnSelector" icon="ui-icon-calculator" />
                    <p:columnToggler datasource="transactionsTable" trigger="toggler" >
                        <p:ajax event="toggle" listener="#{transactionsPage.onToggle}" />
                    </p:columnToggler>
                </p:outputPanel>
            </f:facet>

            <c:forEach var="column" items="#{transactionsPage.columnList}">
                <p:column id="#{column.id}" filterStyleClass="#{column.filterStyleClass}" headerText="#{column.title}" visible="#{column.visible}" width="#{column.width}" filterBy="#{data[column.property]}" filterMatchMode="contains" styleClass="mainPageCompanyColumn">
                    <f:attribute name="rtcCol" value="#{column}"/>
                    <h:outputText value="#{data[column.property]}" />
                </p:column>
            </c:forEach>

        </p:dataTable>

问题如下:

当我想调整上次打开的选项卡中的列大小时,它起作用了,我看到在从托管 bean 调用调整大小方法之前,调用了 primefaces Datatable.class 中的 queueEvent 方法(在此方法决定调用哪个事件),其中 clientId 是正确的 formTabs:tabs:tab1:transactionsTable 然后调用调整大小方法。

但是当我进入另一个选项卡时,queueEvent 方法中的 clientId 保持不变,从最后一个选项卡 openend formTabs:tabs:tab1:transactionsTable 并且我得到以下异常,因此不再调用 resize 方法.

 java.lang.NullPointerException
at org.primefaces.component.datatable.DataTable.findColumnInGroup(DataTable.java:909)
at org.primefaces.component.datatable.DataTable.findColumn(DataTable.java:900)
at org.primefaces.component.datatable.DataTable.queueEvent(DataTable.java:814)
at org.primefaces.behavior.ajax.AjaxBehaviorRenderer.decode(AjaxBehaviorRenderer.java:47)
at javax.faces.component.behavior.ClientBehaviorBase.decode(ClientBehaviorBase.java:132)
at org.primefaces.renderkit.CoreRenderer.decodeBehaviors(CoreRenderer.java:530)
at org.primefaces.component.datatable.DataTableRenderer.decode(DataTableRenderer.java:66)

我假设会发生这种情况,因为数据表的 clientId 未从选项卡更新到数据表,我已将焦点更改为该选项卡。

所以问题是:如何将整个 path/id 更改为新打开的 tab/datatable:

formTabs:tabs:tab0:transactionsTable

因为我的假设是,这就是为什么没有为另一个选项卡调用调整大小方法,然后是最后打开的选项卡。

如果说的不够清楚或者架构不好,那么问题就是 如何在不创建 11 个静态数据表的情况下对 11 个选项卡使用相同的 xhtml page/datatable?

所以,问题似乎出在数据表的 widgetVar 上,因为它为每个数据表的 widgetVar 使用了相同的值,这就是为什么它具有相同的 clientId,因为相同的 clientId 被添加到DOM.

如果您想阅读有关 widgetVar 的信息: http://blog.hatemalimam.com/intro-to-primefaces-widgetvar/

因此,作为结论,我为每个选项卡的 widgetVar 动态设置了一个值,并且 primefaces 数据表中的 clientId class 是正确的,调用了 resize 方法并且它起作用了。