带有 prependId="false" 的 UIForm中断 <f:ajax 渲染> [英] UIForm with prependId="false" breaks <f:ajax render>

查看:19
本文介绍了带有 prependId="false" 的 UIForm中断 <f:ajax 渲染>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对事实背后的想法有疑问,即只有 UIForm 获得了属性 prependId.为什么NamingContainer接口中没有指定属性?您现在可能会说这是因为向后兼容性,但我更愿意打破兼容性,让实现该接口的用户也实现 prependId 事物的方法.

从我的角度来看,关于 UIForm 组件中的 prependId 的主要问题是,它会破坏 findComponent()我希望如果我使用 prependId,那么 NamingContainer 的行为会改变,不仅与渲染有关,而且在想要在组件树中搜索组件时也会发生变化.>

这里有一个简单的例子:

<h:panelGroup id="group"/></h:form>

现在,当我想要获取 panelGroup 组件时,我希望将字符串 "group" 传递给方法 findComponent(),但它找不到任何东西,我必须使用 "test:group" 代替.

具体问题是,当使用带有 prependId="false" 的 ajax 时.ajax 标签期望在属性更新和处理中,值关心命名容器.有点奇怪,当我使用 prependId="false" 时,我必须指定完整的 id 或路径,但没关系.

<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() 实现背后的编程问题.

您对此有何看法,为什么要这样实施?我不可能是第一个遇到这个问题的,但我找不到相关主题?!

解决方案

确实,UIComponent#findComponent() as done by 在以下情况下失败使用 .这个问题是已知的,是一个不会修复":JSF 规范问题 573.

以我的拙见,他们不应该在 JSF 1.2 时代将 prependId 属性添加到 UIForm.这样做只是为了让 j_security_check 用户满意,他们希望为此使用带有 JSF 输入组件的 JSF 表单(j_security_check 需要准确的输入字段名称 j_usernamej_password 不能被配置修改).但是他们并没有完全意识到在 JSF 1.2 期间引入了另一项改进,它使您可以继续使用

而不是坚持使用 代码>.然后 CSS/jQuery 纯粹主义者开始滥用 prependId="false" 以避免在他们选择不当的 CSS 选择器中转义分隔符 :.

永远不要使用prependId="false".

对于 j_security_check,只需使用 或新的 Servlet 3.0 HttpServletRequest#login().另请参阅 在Java EE/JSF 使用 j_security_check.

对于 CSS 选择器,如果您绝对需要一个 ID 选择器(因此不是更可重用的类选择器),只需将感兴趣的组件包装在纯 HTML <div> 中>.

另见:

I have a question about the idea behind the fact, that only UIForm got the attribute prependId. Why is the attribute not specified in the NamingContainer interface? You will now probably say that's because of backward compability but I would preferre breaking the compability and let users which implement that interface, also implement methods for the prependId thing.

The main problem from my perspective about the prependId in the UIForm component is, that it will break findComponent() I would expect that if I use prependId, then the NamingContainer behaviour would change, not only related to rendering but also when wanting to search for components in the component tree.

Here a simple example:

<h:form id="test" prependId="false">
  <h:panelGroup id="group"/>
</h:form>

Now when i want to get the panelGroup component I would expect to pass the string "group" to the method findComponent(), but it won't find anything, I have to use "test:group" instead.

The concrete problem with that is, when using ajax with prependId="false". The ajax tag expects in the attributes update and process, that the values care of naming containers. It's a bit strange that when I use prependId="false" that I have to specify the full id or path, but okay.

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

Well this code will render without problems but it won't update the panelGroup because it cannot find it. The PartialViewContext will contain only the id "group" as element of the renderIds. I don't know if this is expected, probably it is but I don't know the code. Now we come to the point where the method findComponent() can not find the component because the expression passed as parameter is "group" where the method would expect "test:group" to find the component.

One solution is to write your own findComponent() which is the way I chose to deal with this problem. In this method i handle a component which is a NamingContainer and has the property prependId set to false like a normal UIComponent. I will have to do that for every UIComponent which offers a prependId attribute and that is bad. Reflection will help to get around the static definition of types but it's still not a really clean solution.

The other way would be introducing the prependId attribute in the NamingContainer interface and change the behaviour of findComponent() to work like described above.

The last proposed solution would be changing the behaviour of the ajax tag to pass the whole id, but this would only solve the ajax issue and not the programmatic issues behind the findComponent() implementation.

What do you think about that and why the hell is it implemented like that? I can't be the first having this problem, but I wasn't able to find related topics?!

解决方案

Indeed, UIComponent#findComponent() as done by <f:ajax render> fails when using <h:form prependId="false">. This problem is known and is a "Won't fix": JSF spec issue 573.

In my humble opinion, they should never have added the prependId attribute to the UIForm during the JSF 1.2 ages. It was merely done to keep j_security_check users happy who would like to use a JSF form with JSF input components for that (j_security_check requires exact input field names j_username and j_password which couldn't be modified by configuration). But they didn't exactly realize that during JSF 1.2 another improvement was introduced which enables you to just keep using <form> for that instead of sticking to <h:form>. And then CSS/jQuery purists start abusing prependId="false" to avoid escaping the separator character : in their poorly chosen CSS selectors.

Just don't use prependId="false", ever.

For j_security_check, just use <form> or the new Servlet 3.0 HttpServletRequest#login(). See also Performing user authentication in Java EE / JSF using j_security_check.

For CSS selectors, in case you absolutely need an ID selector (and thus not a more reusable class selector), simply wrap the component of interest in a plain HTML <div> or <span>.

See also:

这篇关于带有 prependId="false" 的 UIForm中断 &lt;f:ajax 渲染&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆