在p:datatable中找不到PrimeFaces/JSF组件ID

在p:datatable中找不到PrimeFaces/JSF组件ID,jsf,jsf-2,primefaces,Jsf,Jsf 2,Primefaces,我只是从RichFaces3和4中的PrimeFaces3.3.1开始 <f:facet name="header"> <h:outputText value="Employees" /> </f:facet> <p:column sortBy="#{emp.lastName}"> <f:facet nam

我只是从RichFaces3和4中的PrimeFaces3.3.1开始

            <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>
我有一个数据表,其结构如下:

            <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>
找不到该ID。隐马尔可夫模型。。。。我基本上是从RichFaces复制结构。在这里,删除或编辑行的行按钮不需要:employee表单:。。。前缀我想知道为什么。

            <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>
当给表单一个ID并在PF组件引用前面加上“:”语法时,代码按预期运行:

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

            <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>
为什么p:datatable需要在根JSF ID前面加前缀?也许这是我的代码,但我觉得上面的例子很简单。在任何情况下,使用它都可能导致整个应用程序都有很长的ID

            <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>
我做错了什么

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

PS:我在JBoss AS 7.1.1.Final、Mojarra 2.1.7、PF 3.3.1上,PrimeFaces使用提供的标准JSF算法根据给定的客户端ID查找组件。该算法在前面链接的javadoc中有详细描述。以下是一段相关摘录:

            <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>
搜索表达式由标识符或(与
UIComponent
的id属性或由
UINamingContainer#getSeparatorChar
字符值链接的一系列此类标识符完全匹配。搜索算法应按如下操作,但只要最终结果相同,也可使用替代算法:

            <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>
  • 通过在满足以下条件之一时立即停止,识别将作为搜索基础的
    ui组件
    • 若搜索表达式以分隔符字符(称为“绝对”搜索表达式)开头,则基将是组件树的根
      UIComponent
      。前导分隔符将被剥离,搜索表达式的其余部分将被视为“相对”搜索表达式,如下所述
    • 否则,如果此
      UIComponent
      NamingContainer
      它将作为基础
    • 否则,请搜索此组件的父级。如果遇到
      NamingContainer
      ,则它将作为基础
    • 否则(如果没有遇到
      NamingContainer
      ),根
      ui组件将作为基础
  • 搜索表达式(可能在上一步中修改)现在是一个“相对”搜索表达式,用于在基本组件的范围内定位id匹配的组件(如果有)。匹配的执行如下:
    • 如果搜索表达式是一个简单标识符,则将该值与id属性进行比较,然后递归地通过基本
      UIComponent
      的facet和子级(除非找到了后代
      NamingContainer
      ,则不会搜索其自身的facet和子级)
    • 如果搜索表达式包含多个由分隔符分隔的标识符,则第一个标识符将根据上一个项目符号中的规则用于定位
      NamingContainer
      。然后,
      findComponent()
      将调用此
      NamingContainer
      的方法,传递搜索表达式的其余部分
RichFaces使用相同的算法

            <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>
“reRender”使用
UIComponent.findComponent()
算法(还有一些例外)在组件树中查找组件

            <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>
这些额外的例外情况没有详细描述,但众所周知,相关组件ID(即不以
开头的组件ID)不仅在最近的父级
NamingContainer
的上下文中搜索,而且在同一视图中的所有其他
NamingContainer
组件中搜索(顺便说一句,这是一项相对昂贵的工作)。

(+1)感谢您发布算法:这比具体案例中的具体案例有更多的帮助。
            <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>