2012-08-07 63 views
6

我刚开始与PrimeFaces 3.3.1脱落RichFaces的3和4PrimeFaces/JSF组件ID不从p范围内的值:数据表

我有一个数据表与结构:

  <f:facet name="header"> 
       <h:outputText value="Employees" /> 
      </f:facet> 

      <p:column sortBy="#{emp.lastName}"> 
       <f:facet name="header"> 
        <h:outputText value="Last Name" /> 
       </f:facet> 
       <h:outputText value="#{emp.lastName}" /> 
      </p:column> 

      <p:column> 
       <f:facet name="header"> 
        <h:outputText value="First Name" /> 
       </f:facet> 
       <h:outputText value="#{emp.firstName}" /> 
      </p:column> 

      ... 

      <p:column> 
        <p:commandButton icon="ui-icon ui-icon-trash" 
            value="Remove" 
            process="@this" 
            update="employee-remove-dialog" 
            oncomplete="employeeRemoveDialog.show();"> 
         <f:setPropertyActionListener target="#{employeeManager.currentEmployee}" value="#{emp}" /> 
        </p:commandButton> 
      </p:column> 
     </p:dataTable> 

     <p:dialog header="Remove Employee" 
        modal="true" 
        appendToBody="true" 
        widgetVar="employeeRemoveDialog" 
        id="employee-remove-dialog"> 
      <h:outputText value="Remove employee #{employeeManager.currentEmployee.fullName}?" /> 
      <f:facet name="footer"> 
       <p:commandButton icon="ui-icon ui-icon-check" 
           value="OK" 
           action="#{employeeManager.deleteEmployee}" 
           process="@this" 
           update="employee-list" 
           oncomplete="employeeRemoveDialog.hide();" /> 
       <p:commandButton icon="ui-icon ui-icon-close" 
           value="Cancel" 
           onclick="employeeRemoveDialog.hide();" 
           ajax="false" 
           immediate="true" /> 
      </f:facet> 
     </p:dialog> 

    </h:form> 

然而PrimeFaces抛出异常:

09:36:08,961 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (http-localhost-127.0.0.1-8080-1) Error Rendering View[/employeeList.xhtml]: javax.faces.FacesException: Cannot find component with identifier "employee-remove-dialog" referenced from "j_idt30:employee-list:0:j_idt41". 
    at org.primefaces.util.ComponentUtils.findClientIds(ComponentUtils.java:251) [primefaces-3.3.1.jar:] 
    at org.primefaces.util.AjaxRequestBuilder.addIds(AjaxRequestBuilder.java:102) [primefaces-3.3.1.jar:] 
    at org.primefaces.util.AjaxRequestBuilder.update(AjaxRequestBuilder.java:90) [primefaces-3.3.1.jar:] 
    at org.primefaces.renderkit.CoreRenderer.buildAjaxRequest(CoreRenderer.java:195) [primefaces-3.3.1.jar:] 
    at org.primefaces.component.commandbutton.CommandButtonRenderer.encodeMarkup(CommandButtonRenderer.java:74) [primefaces-3.3.1.jar:] 
    at org.primefaces.component.commandbutton.CommandButtonRenderer.encodeEnd(CommandButtonRenderer.java:49) [primefaces-3.3.1.jar:] 
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at com.sun.faces.renderkit.html_basic.HtmlBasicRenderer.encodeRecursive(HtmlBasicRenderer.java:312) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.renderkit.html_basic.GridRenderer.renderRow(GridRenderer.java:185) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.renderkit.html_basic.GridRenderer.encodeChildren(GridRenderer.java:129) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1779) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at org.primefaces.component.datatable.DataTableRenderer.encodeRegularCell(DataTableRenderer.java:780) [primefaces-3.3.1.jar:] 
    at org.primefaces.component.datatable.DataTableRenderer.encodeRow(DataTableRenderer.java:741) [primefaces-3.3.1.jar:] 
    at org.primefaces.component.datatable.DataTableRenderer.encodeTbody(DataTableRenderer.java:645) [primefaces-3.3.1.jar:] 
    at org.primefaces.component.datatable.DataTableRenderer.encodeRegularTable(DataTableRenderer.java:248) [primefaces-3.3.1.jar:] 
    at org.primefaces.component.datatable.DataTableRenderer.encodeMarkup(DataTableRenderer.java:220) [primefaces-3.3.1.jar:] 
    at org.primefaces.component.datatable.DataTableRenderer.encodeEnd(DataTableRenderer.java:107) [primefaces-3.3.1.jar:] 
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1786) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at javax.faces.render.Renderer.encodeChildren(Renderer.java:168) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:845) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:55) [primefaces-3.3.1.jar:] 
    at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:43) [primefaces-3.3.1.jar:] 
    at org.primefaces.component.layout.LayoutUnitRenderer.encodeEnd(LayoutUnitRenderer.java:51) [primefaces-3.3.1.jar:] 
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:875) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1786) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1782) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:402) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:125) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:288) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) [jsf-impl-2.1.7-jbossorg-2.jar:] 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:594) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] 
    at org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31] 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:] 
    at org.jboss.as.jpa.interceptor.WebNonTxEmCloserValve.invoke(WebNonTxEmCloserValve.java:50) [jboss-as-jpa-7.1.1.Final.jar:7.1.1.Final] 
    at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final] 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:] 
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:] 
    at java.lang.Thread.run(Unknown Source) [rt.jar:1.7.0_04] 

的ID不能被发现。嗯....我基本上从RichFaces复制结构。有删除或编辑行的行按钮不需要:employee-form:...前缀。 我想知道为什么。

当给予形式的ID和前缀来的PF组件引用 ':' 语法的代码运行正常:

<h:form id="employee-form"> 
     <p:dataTable ...> 
      ... 
      <p:column> 
       <h:panelGrid ...> 
        <p:commandButton ... 
            update=":employee-form:employee-remove-dialog" 
            ...> 
         ... 
        </p:commandButton> 
       </h:panelGrid> 
      </p:column> 
     </p:dataTable> 
     <p:dialog ... 
        id="employee-remove-dialog"> 
     </p:dialog> 
    </h:form> 

问:

为什么AP:数据表需要为根JSF ID添加前缀?也许这是我的代码,但发布的示例似乎对我来说很小。在任何情况下,使用这将导致整个应用程序可能存在很长的ID。

我在做什么错?

PS:我是在JBoss AS 7.1.1.Final,钻嘴鱼科2.1.7,3.3.1 PF

回答

13

PrimeFaces使用由UIComponent#findComponent()提供给找到一个给定的客户端ID组件标准JSF算法。该算法在上述javadoc中有详细描述。这里的相关性的提取物:

搜索表达式由任一的标识符(其针对UIComponent的id属性,或一系列由UINamingContainer#getSeparatorChar字符值链接这样的标识符的精确匹配的搜索算法应该如下操作,尽管替代算法的可被使用,只要最终结果是一样的:

  • 识别UIComponent,这将是用于搜索,通过只要满足下列条件之一是停止基见:
    • 如果搜索表达式以分隔符(称为“绝对”搜索表达式)开头,则基数将是组件树的根UIComponent。前面的分隔符将被删除,并且搜索表达式的其余部分将被视为如下所述的“相对”搜索表达式。
    • 否则,如果这个UIComponentNamingContainer它将作为基础。
    • 否则,搜索此组件的父母。如果遇到NamingContainer,它将成为基础。
    • 否则(如果没有遇到NamingContainer)根UIComponent将成为基础。
  • 搜索表达式(在前面的步骤可能被修改)现在是一个“相对”搜索将要使用以定位所述分量(如果有的话)具有匹配的ID表达,基座的范围内零件。
    • 如果搜索表达式是一个简单的标识符,这个值是相对于id属性,然后递归地穿过基座UIComponent的刻面和儿童(不同之处在于如果一个子NamingContainer是:如下进行匹配发现,它自己的方面和孩子不被搜查)。
    • 如果搜索表达式包含多个由分隔符分隔的标识符,则使用第一个标识符按照前一个项目符号点中的规则定位NamingContainer。然后,将调用此NamingContainerfindComponent()方法,传递搜索表达式的其余部分。

RichFaces使用相同的算法"with some additional exceptions"

“重新解析”使用UIComponent.findComponent()算法(有一些额外的例外)找到组件树中的组件。

那些另外的例外是无处中详细描述的,但它的公知的是,相对的组件ID(即那些不开始与:)不仅搜索在最接近父NamingContainer的上下文中,而且在所有其它NamingContainer组件在同一视图中(这是一个相对昂贵的工作)。

+3

(+1)感谢您发布算法:这比混凝土案件更具帮助。 – Ralph 2012-08-23 08:40:58