binding on p:dataTable which is included multiple times causes ID unqiueness exceptions

。_饼干妹妹 提交于 2020-01-16 01:55:48

问题


I'm attempting to use a special PrimeFaces data exporter implementation as being used in this answer:

https://stackoverflow.com/a/14413932/396732

Our use case however is a little more complex, e.g. using Facelets to show the respective datatable for export, which has row expansions with sub tables in them.

insiderListManagerDialogs.xhtml:

<ui:include src="insiderListManagerListDialog.xhtml">
    <ui:param name="idPrefix" value="il-emp" />
    <ui:param name="widgetVarPrefix" value="ilEmp" />
    <ui:param name="dialogTitle" value="#{msg['entity.employee.internal.plural.label']}" />
    <ui:param name="mapPropertyName" value="insiderListEmployeesMap" />
    <ui:param name="sortColumn" value="#{ent.lastTime}" />
    <ui:param name="keyColumnsXhtml" value="listDialogInsiderListKeyColumns.xhtml" />
    <ui:param name="valueColumnsXhtml" value="listDialogEmployeeValueColumns.xhtml" />
</ui:include>

insiderListManagerListDialog.xhtml:

<p:dialog id="#{idPrefix}-il-view-dialog"
          widgetVar="#{widgetVarPrefix}Dialog"
          header="#{dialogTitle}"
          modal="true"
          resizable="false"
          appendToBody="true" 
          onShow="resetFilterInput( '#{idPrefix}' );"
          width="1000"
          height="750">

    <h:form id="#{idPrefix}-il-view-form">
        <p:dataTable id="list-entities"
                     widgetVar="listEntitiesTable"
                     binding="#{table}"
                     value="#{insiderListManager.listInstances}"
                     var="key"
                     scrollable="true"
                     scrollHeight="625"
                     scrollWidth="985"
                     resizableColumns="true"
                     expandedRow="#{insiderListManager.listEntitiesRowTogglerOpen}"
                     filteredValue="#{insiderListManager.filteredEntities}"
                     sortBy="#{sortColumn}"
                     styleClass="bx-datatable-header-hidden-m"
                 tyle="width: 970px;">

            <f:facet name="header">
                <p:inputText id="globalFilter"
                             onkeypress="if (event.keyCode == 13) { listEntitiesTable.filter(); return false;}"
                             size="70"
                             styleClass="bx-dt-header-element" />
                <p:commandButton id="search-btn"
                                 icon="ui-icon bx-icon-search"
                                 value="#{msg['common.action.search.label']}"
                                 process="@this"
                                 onclick="listEntitiesTable.filter(); return false;"
                                 styleClass="bx-dt-header-element" />            
                <p:commandButton title="#{msg['common.action.excelExport.all.hint']}"
                                 icon="ui-icon bx-icon-excel"
                                 action="#{insiderListManager.exportXls( table )}"
                                 ajax="false"
                                 styleClass="bx-button-border bx-dt-header-element" />
                 <div class="bx-clear-float" />
            </f:facet>

            <p:column width="15"
                      resizable="false">

            ...

            <p:rowExpansion> 
                <p:dataTable value="#{insiderListManager[mapPropertyName].get(key)}"
                             var="value">

                    <ui:include src="#{valueColumnsXhtml}" />

                </p:dataTable>
            </p:rowExpansion> 
        </p:dataTable>

        <h:panelGroup id="button-panel" layout="block" styleClass="left-button-panel mt-5px">
            <p:commandButton id="toggle-button"
                             icon="#{insiderListManager.listEntitiesRowTogglerOpen ? 'ui-icon ui-icon-circle-triangle-e' : 'ui-icon ui-icon-circle-triangle-s'}"
                             value="#{insiderListManager.listEntitiesRowTogglerOpen ? msg['common.action.collapseAll.label'] : msg['common.action.expandAll.label']}"
                             process="@this"
                             update="@form">
                <f:setPropertyActionListener target="#{insiderListManager.listEntitiesRowTogglerOpen}"
                                             value="#{not insiderListManager.listEntitiesRowTogglerOpen}" />
            </p:commandButton>
        </h:panelGroup>

    </h:form>
</p:dialog>

Note the

<p:commandButton title="..."
                 icon="ui-icon bx-icon-excel"
                 action="#{insiderListManager.exportXls( table )}"
                 ... />

which is using the bound data table as described in the link posted at the top.

We are using JSF 2.1 (Mojarra 2.1.22 - and we cannot switch to MyFaces) which allows expressions to construct IDs like #{idPrefix}-il-view-dialog from a <ui:param name="idPrefix" value="il-emp" />.

However, we are getting ID uniqueness exception:

Caused by: java.lang.IllegalStateException: Component ID il-emp-il-view-form:list-entities:globalFilter has already been found in the view.  
    at com.sun.faces.util.Util.checkIdUniqueness(Util.java:846)
    at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
    at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
    at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
    at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
    at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
    at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
    at com.sun.faces.util.Util.checkIdUniqueness(Util.java:830)
    at com.sun.faces.application.view.StateManagementStrategyImpl.saveView(StateManagementStrategyImpl.java:144)
    at com.sun.faces.application.StateManagerImpl.saveView(StateManagerImpl.java:133)
    at com.sun.faces.application.view.WriteBehindStateWriter.flushToWriter(WriteBehindStateWriter.java:225)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:419)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
    at com.ocpsoft.pretty.faces.application.PrettyViewHandler.renderView(PrettyViewHandler.java:163)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594)
    ... 49 more

Same happens to other buttons with explicit IDs if omitted, e.g. the search button (<p:commandButton id="search-btn" ...).

QUESTION:

Why is this happening and how can we avoid this problem when we are bound to using PrimeFaces dialogs for each use case displayed? (we have more than one dialog)

Note that when removing the <p:dataTable ... binding="..." the page works correctly.


回答1:


You're basically binding physically different <p:dataTable> components to one and same EL variable. If this EL variable is not null (i.e. already set by a previous component in the same view), then JSF will reuse it instead of creating a new one, and override all of its attributes during view build time, resulting in "weird" behavior during view render time and potential duplicate component ID errors during state saving.

In your specific case, you can use UIComponent#getNamingContainer() to directly reference the parent <p:dataTable> component from inside a child component.

<p:dataTable ... (NO binding!)>
    ...
    <p:comandButton ... action="#{bean.exportXls(component.namingContainer)}" />

Might it happen that it's nested in another NamingContainer component, then you need to use #{component.namingContainer.parent.namingContainer} instead. And so forth for multiple ones.



来源:https://stackoverflow.com/questions/30485162/binding-on-pdatatable-which-is-included-multiple-times-causes-id-unqiueness-exc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!