在p:datatable中找不到PrimeFaces/JSF组件ID
我只是从RichFaces3和4中的PrimeFaces3.3.1开始在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
<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属性进行比较,然后递归地通过基本
的facet和子级(除非找到了后代UIComponent
,则不会搜索其自身的facet和子级)NamingContainer
- 如果搜索表达式包含多个由分隔符分隔的标识符,则第一个标识符将根据上一个项目符号中的规则用于定位
。然后,NamingContainer
将调用此findComponent()
的方法,传递搜索表达式的其余部分NamingContainer
- 如果搜索表达式是一个简单标识符,则将该值与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>
“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>