带有 prependId="false" 的 UIForm 中断 <f:ajax render>
Posted
技术标签:
【中文标题】带有 prependId="false" 的 UIForm 中断 <f:ajax render>【英文标题】:UIForm with prependId="false" breaks <f:ajax render> 【发布时间】:2011-11-16 22:21:21 【问题描述】:我对事实背后的想法有疑问,即只有 UIForm
获得了属性 prependId
。为什么NamingContainer
接口中没有指定属性?您现在可能会说这是因为向后兼容性,但我更愿意打破兼容性并让实现该接口的用户也实现 prependId 事物的方法。
从我的角度来看,UIForm
组件中 prependId 的主要问题是,它会破坏 findComponent()
我希望如果我使用prependId
,那么NamingContainer
的行为会发生变化,这不仅与渲染有关,而且在想要在组件树中搜索组件时也会发生变化。
这里是一个简单的例子:
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
现在,当我想获取 panelGroup 组件时,我希望将字符串 "group"
传递给方法 findComponent()
,但它找不到任何东西,我必须改用 "test:group"
。
具体的问题是,当使用带有prependId="false"
的ajax 时。 ajax 标记期望在属性更新和处理中,值关心命名容器。有点奇怪,当我使用prependId="false"
时,我必须指定完整的 id 或路径,但没关系。
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
<h:form id="test1" prependId="false">
<h:commandButton value="go">
<f:ajax render="test:group"/>
</h:commandButton>
</h:form>
好吧,这段代码将毫无问题地呈现,但它不会更新 panelGroup,因为它找不到它。 PartialViewContext
将仅包含 id "group"
作为 renderIds 的元素。我不知道这是否是预期的,可能是这样,但我不知道代码。现在我们到了findComponent()
方法找不到组件的地步,因为作为参数传递的表达式是"group"
,而该方法期望"test:group"
找到组件。
一种解决方案是编写自己的findComponent()
,这是我选择处理此问题的方式。在这个方法中,我处理一个组件,它是一个NamingContainer
,并且像普通的UIComponent
一样将属性 prependId 设置为 false。对于每个提供 prependId 属性的UIComponent
,我都必须这样做,这很糟糕。反射将有助于绕过类型的静态定义,但它仍然不是一个真正干净的解决方案。
另一种方法是在NamingContainer
接口中引入 prependId 属性,并将findComponent()
的行为更改为如上所述。
最后提出的解决方案是更改 ajax 标记的行为以传递整个 id,但这只会解决 ajax 问题,而不是 findComponent()
实现背后的编程问题。
您对此有何看法?为什么要这样实施?我不可能是第一个遇到这个问题的人,但是我找不到相关的主题?!
【问题讨论】:
一个确实知道如何揭示事物的程序员编写的精美案例。谢谢克里斯蒂安。 【参考方案1】:确实,<f:ajax render>
所做的 UIComponent#findComponent()
在使用 <h:form prependId="false">
时会失败。这个问题是已知的并且是“无法修复”:JSF spec issue 573。
以我的拙见,在 JSF 1.2 时代,他们不应该将 prependId
属性添加到 UIForm
。这样做只是为了让 j_security_check
用户满意,他们希望使用带有 JSF 输入组件的 JSF 表单(j_security_check
需要精确的输入字段名称 j_username
和 j_password
不能通过配置修改) .但他们并没有完全意识到在 JSF 1.2 期间引入了另一项改进,它使您能够继续使用 <form>
而不是坚持使用 <h:form>
。然后 CSS/jQuery 纯粹主义者开始滥用 prependId="false"
以避免在他们选择不当的 CSS 选择器中转义分隔符 :
。
永远不要使用prependId="false"
。
对于j_security_check
,只需使用<form>
或新的Servlet 3.0 HttpServletRequest#login()
。另见Performing user authentication in Java EE / JSF using j_security_check。
对于 CSS 选择器,如果您绝对需要 ID 选择器(因此不需要更可重用的类选择器),只需将感兴趣的组件包装在纯 html <div>
或 <span>
中。
另见:
How to select JSF components using jQuery? How to use JSF generated HTML element ID with colon ":" in CSS selectors? By default, JSF generates unusable ids, which are incompatible with css part of web standards【讨论】:
好吧,我遇到了 findComponent() 算法的另一个“问题”,或者它是什么不同的东西。当我尝试在其外部更新数据表的特定行时,找不到组件 ID。我使用这样的东西: 为什么ajax标签不能解析组件?我检查了来源,但不知道为什么它不起作用。我应该将父 NamingContainer 作为查找的基础,然后找到 dataTable,迭代到行并最终找到 subElement,但它没有! Ajax标签有点奇怪……以上是关于带有 prependId="false" 的 UIForm 中断 <f:ajax render>的主要内容,如果未能解决你的问题,请参考以下文章
总是运行带有 failOnError="false" 的 Liquibase changeSet?
带有 FriendlyUrls 和 debug="false" 的 ASP.NET WebForms 项目在生产中引发 404
带有 Rails UJS 的 jQuery Mobile 在使用 data-method="delete" 的链接上尊重 data-ajax="false"