简体   繁体   English

带有prependId =“ false”的UIForm中断<f:ajax render>

[英]UIForm with prependId=“false” breaks <f:ajax render>

I have a question about the idea behind the fact, that only UIForm got the attribute prependId . 我对事实背后的想法有一个疑问,那就是只有UIForm才具有属性prependId Why is the attribute not specified in the NamingContainer interface? 为什么在NamingContainer接口中未指定属性? 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. 您现在可能会说这是由于向后兼容性,但是我更希望破坏兼容性,让实现该接口的用户也为prependId事情实现方法。

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. 从我的角度来看,关于UIForm组件中的UIForm的主要问题是,它将破坏findComponent()我希望如果我使用prependId ,则NamingContainer行为将发生变化,不仅与呈现有关,而且还与想要搜索时有关组件树中的组件。

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. 现在,当我想获取panelGroup组件时,我希望将字符串"group"传递给方法findComponent() ,但找不到任何东西,我必须改用"test:group"

The concrete problem with that is, when using ajax with prependId="false" . 具体的问题是,将ajax与prependId="false" The ajax tag expects in the attributes update and process, that the values care of naming containers. ajax标记在属性更新和处理中期望值关心命名容器。 It's a bit strange that when I use prependId="false" that I have to specify the full id or path, but okay. 有点奇怪,当我使用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>

Well this code will render without problems but it won't update the panelGroup because it cannot find it. 好的,这段代码可以毫无问题地呈现,但是由于找不到它,因此不会更新panelGroup。 The PartialViewContext will contain only the id "group" as element of the renderIds. PartialViewContext将仅包含id "group"作为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. 现在我们到了点,因为方法作为参数传递的表达式是"group" ,所以方法findComponent()找不到组件,该方法希望"test:group"找到组件。

One solution is to write your own findComponent() which is the way I chose to deal with this problem. 一种解决方案是编写自己的findComponent() ,这是我选择处理此问题的方式。 In this method i handle a component which is a NamingContainer and has the property prependId set to false like a normal UIComponent . 在这种方法中,我像正常的UIComponent一样处理一个组件NamingContainer并将其prependId属性设置为false。 I will have to do that for every UIComponent which offers a prependId attribute and that is bad. 我将必须为每个提供prependId属性的UIComponent这样做,这很糟糕。 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. 另一种方法是在NamingContainer接口中引入prependId属性,并将findComponent()的行为更改为如上所述。

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. 最后提出的解决方案是更改ajax标记的行为以传递整个id,但这只能解决ajax问题,不能解决findComponent()实现背后的编程问题。

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"> . 实际上,当使用<h:form prependId="false">时,由<f:ajax render>完成的UIComponent#findComponent()失败。 This problem is known and is a "Won't fix": JSF spec issue 573 . 此问题是已知的,并且是“无法解决”的问题JSF规范问题573

In my humble opinion, they should never have added the prependId attribute to the UIForm during the JSF 1.2 ages. 在我的愚见,他们不应该添加prependId属性的UIForm在JSF 1.2时代。 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). 这样做只是为了使j_security_check用户满意,他们希望为此使用带有JSF输入组件的JSF表单( j_security_check需要准确的输入字段名称j_usernamej_password ,而配置不能修改它们)。 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> . 但是他们并没有完全意识到,在JSF 1.2中引入了另一项改进,使您可以继续使用<form>而不是坚持使用<h:form> And then CSS/jQuery purists start abusing prependId="false" to avoid escaping the separator character : in their poorly chosen CSS selectors. 然后CSS / jQuery纯粹主义者开始滥用prependId="false"以避免转义分隔符:在他们选择不佳的CSS选择器中。

Just don't use prependId="false" , ever. 只是永远不要使用prependId="false"

For j_security_check , just use <form> or the new Servlet 3.0 HttpServletRequest#login() . 对于j_security_check ,只需使用<form>或新的Servlet 3.0 HttpServletRequest#login() See also Performing user authentication in Java EE / JSF using j_security_check . 另请参阅使用j_security_check在Java EE / JSF中执行用户认证

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> . 对于CSS选择器,万一您绝对需要一个ID选择器(因此不需要更可重用的类选择器),只需将所需的组件包装在纯HTML <div><span>

See also: 也可以看看:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM