问题描述
我有一个用JSF 2.0 + PrimeFaces 3.4编写的标记库,现在我正尝试更新到JSF 2.2和PrimeFaces 4.0.但是我意识到传递给组件的属性值在复合组件中进行了评估,并导致呈现错误的id.
I have a tag library which was written in JSF 2.0 + PrimeFaces 3.4, now i am trying to update to JSF 2.2 and PrimeFaces 4.0.But i realized that the value of attributes passed to component evaluated in composite component and it leads to wrong id for rendering.
enum.xhtml(复合组件)
enum.xhtml (composite component)
<cc:interface>
<cc:attribute name="render" default="@this"/>
.....
</cc:interface>
<cc:implementation>
<h:selectOneMenu ......../>
<p:ajax update="#{cc.attrs.render}" process="#{cc.attrs.execute}" />
</cc:implementation>
用法:
<t:enum id="authenticationSource" value="#{authenticationStrategy}" .....
render=":#{cc.clientId}:tabView:passwordVisibility"/>
渲染属性值:#{cc.clientId}:tabView:passwordVisibility
应该是
:j_idt1:j_idt3:j_idt5:editorDialog:j_idt39:j_idt40:tabView:passwordVisibility`
但其评估为
:j_idt1:j_idt3:j_idt5:editorDialog:j_idt39:j_idt40:tabView:autheticationSource:tabView:passwordVisibility
在复合组件中评估渲染的属性值,并导致错误.应该评估它的使用位置,就像在JSF 2.0中那样.是否有任何配置属性或任何可克服此错误的内容.
Attribute value of render is evaluated in composite component and it caused to error. It should be evaluated where it is used and it was like that in JSF 2.0.Is there any configuration property or anything to overcome this error.
我正在使用Wildfly 8.1.0-Final
I'm using wildfly 8.1.0-Final
推荐答案
此组合没有正确设计.您不应该在组合的上下文之外使用#{cc.clientId}
.更一般而言,您不应从组合外部了解有关组合内部的任何信息.复合材料本身应该为此担心.
This composite is not rightly designed. You're not supposed to use #{cc.clientId}
outside the composite's context. More generally, you're not supposed to know anything about the composite's internals from outside the composite. The composite itself should worry about this.
如果彼此嵌套复合组件,则此构造将失败.然后,#{cc}
实际上将引用当前"复合组件.也许您所依赖的是较早的JSF实现中的错误,该错误中#{cc}
范围未在嵌套的复合组件之后正确清除(即,它将引用最后分配的值而不是当前上下文中可用的值).
This construct will fail if you're nesting composite components in each other. The #{cc}
would then actually refer the "current" composite component. Perhaps you were relying on a bug in an older JSF implementation where the #{cc}
scope isn't properly being cleared out after the nested composite component (i.e. it would refer the last assigned value instead of the value available in the current context).
仅由于与常规标记文件/includes相比,其零配置性质,您可能只是出于错误的目的而过度使用复合组件.有关何时确切使用一个或另一个的详细信息,请转到到目前为止,仅在要绑定一堆组件时才使用复合组件与单个 bean属性紧密相关的组件,因此,当然与具有多个属性的整个" bean无关.
Perhaps you're victim of overusing composite components for the wrong puspose only and only because of the zero-configuration nature as compared to regular tagfiles/includes. For detail as to when exactly to use the one or other, head to When to use <ui:include>, tag files, composite components and/or custom components? To the point, use a composite only and only if you want to bind a bunch of closely related components to a single bean property, and thus certainly not to a "whole" bean with several properties.
如果您完全肯定复合材料是满足您需求的正确解决方案,并且/或者您已经对复合材料进行了相应的重构以消除上述的滥用,那么有两种可能的方法可将客户行为应用于复合材料组件,具体取决于具体的功能要求(如有必要,您甚至可以将两种方法结合使用).
If you're absolutely positive that a composite is the right solution for your requirement, and/or you've refactored the composite accordingly to eliminate the mentioned misuse, then there are 2 possible approaches for applying client behavior on the composite component, depending on the concrete functional requirement (you can even combine the both ways if necessary).
-
如果要让复合ajax渲染组件到外部,请将
<p:ajax>
(或<f:ajax>
)外部化为<cc:clientBehavior>
:
If you want to let the composite ajax-render a component outside the composite, externalize
<p:ajax>
(or<f:ajax>
) as<cc:clientBehavior>
:
<cc:interface>
<cc:clientBehavior name="myCustomEventName" targets="idOfTargetComponent" event="valueChange" />
...
</cc:interface>
<cc:implementation>
<h:selectOneMenu id="idOfTargetComponent" ...>
<f:selectItems ... />
</h:selectOneMenu>
</cc:implementation>
将用作:
<t:enum ...>
<p:ajax event="myCustomEventName" update=":absoluteClientIdOfComponentOUTSIDEComposite" />
</t:enum>
<x:someComponent id="idOfComponentOUTSIDEComposite" />
如果要让复合文件在复合文件内部 内ajax渲染组件,则让复合文件自己完成所有操作.
If you want to let the composite ajax-render a component inside the composite, then let the composite do it all by itself.
<cc:interface>
...
</cc:interface>
<cc:implementation>
<h:selectOneMenu ...>
<f:selectItems ... />
<p:ajax update="idOfComponentINSIDEComposite" />
</h:selectOneMenu>
<x:someComponent id="idOfComponentINSIDEComposite" />
</cc:implementation>
并以通常的方式使用它:
And use it the usual way:
<t:enum ... />
这篇关于升级到JSF 2.2后,#{cc.clientId}的组合评估错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!