在 JSF2/PrimeFaces 中命名容器



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中,例如:AccordionPanelCarouselColumnsDataGridDataListDataScrollerDataTableRingSubTableTabViewTreeTreeTable

命名容器对组件 ID 的影响

  1. 默认行为

命名容器为其子组件提供命名范围。所以它总是给他的孩子 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"。

  1. 更改组件名称分隔符(从 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>
  1. UIForm 属性 "prependId">

为了避免向子组件添加范围,有一个属性(仅在 UIForm 组件中)。但这不是推荐的解决方案。以 uiform-with-prependid-false-breaks-fajax-render

组件 ID 用法(例如在"更新"、"进程"中)

  1. 整个标识

您可以使用整个 id:"componentParent:component"。不建议这样做(代码将是脆弱的;任何 id 更改都会导致在许多地方需要更改 id)。

  1. 同一命名容器级别的相对 id

在一个命名容器中,您可以使用简单的组件 ID。

  1. 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)"

相当强大的工具。

最新更新