#cc.clientId 在升级到 JSF 2.2 后在错误的组合中评估
Posted
技术标签:
【中文标题】#cc.clientId 在升级到 JSF 2.2 后在错误的组合中评估【英文标题】:#cc.clientId evaluated in wrong composite after upgrading to JSF 2.2#cc.clientId 在升级到 JSF 2.2 后在错误的组合中评估 【发布时间】:2014-11-18 23:42:38 【问题描述】:我有一个用 JSF 2.0 + PrimeFaces 3.4 编写的标签库,现在我正在尝试更新到 JSF 2.2 和 PrimeFaces 4.0。 但是我意识到传递给组件的属性值是在复合组件中评估的,它会导致渲染的 id 错误。
enum.xhtml(复合组件)
<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
render 的属性值在复合组件中进行评估,并导致错误。它应该在使用它的地方进行评估,就像在 JSF 2.0 中一样。 是否有任何配置属性或任何东西可以克服这个错误。
我正在使用 Wildfly 8.1.0-Final
【问题讨论】:
也许t:enum
周围的任何元素都变成了命名容器?是否有 ID 为 autheticationSource
的元素?
【参考方案1】:
这个组合的设计不正确。您不应该在复合上下文之外使用#cc.clientId
。更一般地说,您不应该从复合材料外部了解复合材料的内部结构。复合材料本身应该担心这一点。
如果您将复合组件相互嵌套,此构造将失败。然后#cc
将实际引用“当前”复合组件。也许您依赖于旧 JSF 实现中的一个错误,其中 #cc
范围在嵌套复合组件之后没有被正确清除(即,它将引用最后分配的值而不是当前上下文中可用的值)。
也许您只是为了错误的目的而过度使用复合组件的受害者,并且仅仅是因为与常规标记文件/包含相比的零配置性质。有关何时使用一个或另一个的详细信息,请访问When to use <ui:include>, tag files, composite components and/or custom components? 重点是,仅当您想将一堆密切相关的组件绑定到一个 single bean 时才使用组合属性,因此当然不是具有多个属性的“完整” bean。
如果您绝对肯定复合材料是满足您要求的正确解决方案,并且/或者您已相应地重构复合材料以消除上述误用,那么有 2 种可能的方法可将客户端行为应用于复合组件,取决于具体的功能要求(如果需要,您甚至可以将这两种方式结合起来)。
如果您想让复合 ajax 渲染组件在复合之外,请将 <p:ajax>
(或 <f:ajax>
)外部化为 <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-render 一个组件内部复合,然后让复合自己做这一切。
<cc:interface>
...
</cc:interface>
<cc:implementation>
<h:selectOneMenu ...>
<f:selectItems ... />
<p:ajax update="idOfComponentINSIDEComposite" />
</h:selectOneMenu>
<x:someComponent id="idOfComponentINSIDEComposite" />
</cc:implementation>
并以通常的方式使用它:
<t:enum ... />
【讨论】:
对我来说,这与零配置无关。它是关于能够定义一个接口,而不是一堆 ui:params 甚至不适用于正确的方法表达式。我想念 facelet 模板中的客户行为、行动来源和价值持有者。 方法表达式和动作来源:这个问题已知,使用<o:methodParam>
。客户端行为:只需使用<ui:define/insert>
。价值持有者:应该工作。以上是关于#cc.clientId 在升级到 JSF 2.2 后在错误的组合中评估的主要内容,如果未能解决你的问题,请参考以下文章
我应该使用带有 render 属性的 ui:fragment 来有条件地在带有 JSF 2.2 的 Facelets 中呈现 HTML 标记吗?
在 JBoss 5.1.1 上将 JSF 从 1.2 升级到 2.1
如何使用指定版本2.3的JSF Facet创建Eclipse动态Web项目?
升级到 JSF 2.3 后,@Inject 在 @FacesConverter 中不起作用