PrimeFaces中可能的命名容器是什么?为什么当我们要使用update=":mainForm:MainAccordian:userNameTextbox"
更新窗体上的某些 UI 控件时,需要为 Ajax 更新调用附加命名容器 ID?
素数面中可能的命名容器是什么
在JSF中,命名容器派生自UINamingContainer。
为什么当我们想要使用 update=":mainForm:MainAccordian:userNameTextbox 更新窗体上的某些 UI 控件时,需要为 Ajax 更新调用附加命名容器 ID">
比方说,<h:outputText value="test1" id="userNameTextbox" />
,你向页面添加了另一个<h:outputText value="test2" id="userNameTextbox" />
,你会得到一个错误,说你有一个重复的ID。你可以在 JavaDoc for UIComponent.setId(String) 中查找它:
设置此 UIComponent 的组件标识符(如果有)。组件标识符必须遵守以下语法限制: 不能是零长度字符串。 第一个字符必须是字母或下划线 ('')。 后续字符必须是字母、数字、下划线 (">") 或短划线 ("-")。
.. 此外,对您很重要:
指定的标识符在作为命名容器的最近祖先 UIComponent 的后代的所有组件(包括分面)中必须是唯一的,或者在整个组件树的范围内(如果没有命名容器的此类祖先)。
意味着在同一个命名容器下不能有两个具有相同 ID 的组件(如果你根本没有命名容器,则整个树都算作命名容器)。 因此,您需要添加一个命名容器,例如<h:form id="myNamingContainer" />
让我们举个例子:
<h:outputText value="test1" id="userNameTextbox" />
<h:form id="container1">
<h:outputText value="test2" id="userNameTextbox" />
</h:form>
<h:form id="container2">
<h:outputText value="test3" id="userNameTextbox" />
</h:form>
.. 并且您想对用户名文本框进行更新。您指的是哪个用户名文本框,因为有 3 个?
第一个? 然后更新用户名文本框
第二个?然后更新容器 1:用户名文本框
第三个? 然后更新容器 2:用户名文本框
在让 IntelliJ 扫描我所有的 JAR 以查找javax.faces.component.NamingContainer
的实现后,我发现:
来自 PrimeFaces 5.3
- 手风琴面板
- 旋转 木马
- 列
- 数据网格
- 数据列表
- 数据滚动器
- 数据表
- 页
- 戒指
- 子表
- 子视图
- 标签视图
- 树表
- UIData
- UITabPanel
来自 MyFaces 2.1
- Html数据表
- HtmlForm
- UITree
- UIForm
在素数面中命名容器
正如我们在 JSF 参考中看到的
命名容器是一个接口,必须由任何想要成为命名容器的 UIComponent 实现。命名容器会影响 UIComponent.findComponent(java.lang.String) 和 UIComponent.getClientId() 方法的行为;
因此,要在PF中找到命名容器,您需要检查NamingContainer
接口的层次结构。在Eclipse中,您可以通过NamingContainer
上的Ctrl+T快捷方式执行此操作。
在PF 5.3中,例如:AccordionPanel
,Carousel
,Columns
,DataGrid
,DataList
,DataScroller
,DataTable
,Ring
,SubTable
,TabView
,Tree
,TreeTable
。
命名容器对组件 ID 的影响
- 默认行为
命名容器为其子组件提供命名范围。所以它总是给他的孩子 id 添加前缀。所以子组件的id是:parent_component_id".concat(":").concat("component_id")
。 我在JavaServer Faces 2.0中读到过一个专业提示,完整参考,即使您没有将NamingContainer添加到页面中,它也总是由JSF本身自动添加:)这种创建还存在特殊的算法(第 11 章:构建自定义 UI 组件 ->名为"为复合组件创建顶级组件的规则"的框)。当然,当您不设置 id 时,它会自动生成(例如 j_idt234)。因此,完整的组件 ID 可能如下所示:"j_idt123:j_idt234:j_idt345"。
- 更改组件名称分隔符(从 JSF 2.x 开始)
有一种方法可以覆盖默认组件名称分隔符 (":")。您可以在 web 中将其定义为名称为javax.faces.SEPARATOR_CHAR
的上下文参数.xml 。例如:
<context-param>
<param-name>javax.faces.SEPARATOR_CHAR</param-name>
<param-value>-</param-value>
</context-param>
- UIForm 属性 "prependId">
为了避免向子组件添加范围,有一个属性(仅在 UIForm 组件中)。但这不是推荐的解决方案。以 uiform-with-prependid-false-breaks-fajax-render
组件 ID 用法(例如在"更新"、"进程"中)
- 整个标识
您可以使用整个 id:"componentParent:component"。不建议这样做(代码将是脆弱的;任何 id 更改都会导致在许多地方需要更改 id)。
- 同一命名容器级别的相对 id
在一个命名容器中,您可以使用简单的组件 ID。
- PrimeFaces Search Expression Framework
如果您不知道此功能,请查看PrimeFaces文档。Prime Faces为搜索表达式框架提供了几个非常有用的机制。
您可以按关键字搜索。
关键字是引用组件的更简单方法,它们解析为 ids,以便在 id 发生更改时,引用不需要更改。 核心JSF提供了几个关键字,PrimeFaces提供了更多 以及复合表达式支持。
示例:@this
(当前组件)、@form
(最接近祖先形式)、@namingcontainer
(最接近祖先命名容器)、@parent
、@widgetVar(name)
。 您还可以在相当复杂的路径(复合表达式)中混合这些关键字,例如:@form:@parent
、@this:@parent:@parent
PF给你的第二种可能性是PrimeFaces Selectors(PFS)。
PFS 将 jQuery Selector API 与 JSF 组件引用集成在一起 模型,以便可以使用jQuery选择器API完成引用 而不是基于核心 ID 的 JSF 模型。
因此,您可以例如:
- 按
update="@(form)"
更新所有表单元素 - 按
update="@(.ui-datatable)"
更新所有数据表 - 更新具有名为"myStyle"的样式类的所有组件
update="@(.myStyle)"
相当强大的工具。