2012-08-07 38 views
6

Tôi chỉ bắt đầu với PrimeFaces 3.3.1 sắp tắt RichFaces 3 và 4.PrimeFaces/JSF ID thành phần không tìm thấy từ bên trong p: DataTable

Tôi có một DataTable với cấu trúc:

  <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> 

Tuy nhiên PrimeFaces ném một ngoại lệ:

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 không thể được tìm thấy. Hmm .... Tôi về cơ bản đã sao chép cấu trúc từ RichFaces. Có nút hàng để xóa hoặc chỉnh sửa hàng không cần tiền tố: employee-form: .... Tôi tự hỏi tại sao.

Khi đưa ra các hình thức một ID và tiền tố tài liệu tham khảo phần PF với ':' cú pháp mã chạy như mong đợi:

<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> 

Q:

Tại sao ap: DataTable cần thế nào để tiền tố ID gốc JSF? Có lẽ đó là mã của tôi, nhưng ví dụ được đăng dường như là tối thiểu đối với tôi. Trong mọi trường hợp, việc sử dụng điều này sẽ dẫn đến các ID dài có thể trên tất cả các ứng dụng.

Tôi đang làm gì sai?

PS: Tôi đang trên JBoss AS 7.1.1.Final, cá móm 2.1.7, 3.3.1 PF

Trả lời

13

PrimeFaces sử dụng thuật toán JSF tiêu chuẩn theo quy định của UIComponent#findComponent() để tìm các thành phần của một ID khách hàng nhất định. Thuật toán được mô tả chi tiết trong javadoc aforelinked. Dưới đây là một trích liên quan:

Một biểu tìm kiếm bao gồm hoặc là một định danh (mà là lần xuất hiện chính xác đối với các tài sản id của một UIComponent, hoặc một loạt các mã nhận dạng đó được liên kết bởi các giá trị UINamingContainer#getSeparatorChar nhân vật Các tìm kiếm. thuật toán nên hoạt động như sau, mặc dù alogrithms thay thế có thể được sử dụng miễn là kết quả cuối cùng là như nhau:

  • Xác định UIComponent đó sẽ là cơ sở cho việc tìm kiếm, bằng cách ngăn chặn càng sớm là một trong những điều kiện sau là đã gặp:
    • Nếu biểu thức tìm kiếm bắt đầu bằng ký tự dấu tách (được gọi là biểu thức tìm kiếm "tuyệt đối"), cơ sở sẽ là gốc UIComponent của cây thành phần. Ký tự dấu tách hàng đầu sẽ bị tước đi và phần còn lại của biểu thức tìm kiếm sẽ được coi là biểu thức tìm kiếm "tương đối" như được mô tả bên dưới.
    • Nếu không, nếu điều này UIComponentNamingContainer, nó sẽ làm cơ sở.
    • Nếu không, hãy tìm kiếm phụ huynh của thành phần này. Nếu gặp phải NamingContainer, nó sẽ là cơ sở.
    • Nếu không (nếu không có NamingContainer gặp phải) gốc UIComponent sẽ là cơ sở.
  • Biểu thức tìm kiếm (có thể được sửa đổi trong bước trước) hiện là biểu thức tìm kiếm "tương đối" sẽ được sử dụng để định vị thành phần (nếu có) có id phù hợp, trong phạm vi của cơ sở thành phần. Trận đấu được thực hiện như sau:
    • Nếu biểu thức tìm kiếm là một định danh đơn giản, giá trị này được so sánh với tài sản id, và sau đó đệ quy qua các khía cạnh và trẻ em của các cơ sở UIComponent (trừ rằng nếu một hậu duệ NamingContainer là tìm thấy, các khía cạnh và trẻ em của nó không được tìm kiếm).
    • Nếu biểu thức tìm kiếm bao gồm nhiều số nhận dạng được phân cách bằng ký tự dấu tách, số nhận dạng đầu tiên được sử dụng để định vị NamingContainer theo các quy tắc trong dấu đầu dòng trước đó. Sau đó, phương thức findComponent() của số này NamingContainer sẽ được gọi, chuyển phần còn lại của biểu thức tìm kiếm.

RichFaces sử dụng cùng một thuật toán "with some additional exceptions".

"reRender" sử dụng UIComponent.findComponent() thuật toán (với một số ngoại lệ bổ sung) để tìm các thành phần trong cây thành phần.

Những trường hợp ngoại lệ bổ sung có nơi nào một cách chi tiết mô tả, nhưng nó cũng được biết rằng ID thành phần tương đối (tức là những người không bắt đầu với :) không chỉ tìm kiếm trong bối cảnh phụ huynh gần NamingContainer, mà còn trong tất cả NamingContainer khác các thành phần trong cùng một chế độ xem (đây là một công việc tương đối đắt tiền).

+3

(+1) Cảm ơn bạn đã đăng thuật toán: Đó là trợ giúp nhiều hơn nhiều so với bê tông cho trường hợp cụ thể. – Ralph

Các vấn đề liên quan