升级到JSF 2.2后,#{cc.clientId}在错误的复合中进行了评估

时间:2014-09-24 12:59:45

标签: jsf jsf-2.2 composite-component

我有一个用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

渲染的属性值在复合组件中计算,导致错误。它应该在它被使用的地方进行评估,就像在JSF 2.0中一样。 是否有任何配置属性或任何东西来克服此错误。

我正在使用wildfly 8.1.0-Final

1 个答案:

答案 0 :(得分:4)

这种复合材料设计不正确。您不应该在复合的上下文之外使用#{cc.clientId}。更一般地说,你不应该从复合材料之外了解复合材料的内部构件。复合材料本身应该担心这一点。

如果您将复合组件嵌套在一起,则此构造将失败。 #{cc}实际上会引用&#34;当前&#34;复合材料。也许你依赖于旧的JSF实现中的一个错误,其中#{cc}范围在嵌套的复合组件之后没有被正确清除(即它将引用最后指定的值而不是可用的值。当前背景)。

也许你是过度使用复合组件的受害者,只是因为与常规标签文件/包含相比,零配置性质。有关何时使用其中一个的详细信息,请前往When to use <ui:include>, tag files, composite components and/or custom components?到目前为止,仅使用复合,并且仅当您要将一堆密切相关的组件绑定到单个 bean属性,因此肯定不会对整个&#34;有几个属性的bean。

如果您绝对肯定复合材料是满足您需求的正确解决方案,并且/或您已相应地重构复合材料以消除上述误用,则有两种可能的方法来应用客户端行为在复合材料部件上,取决于具体的功能要求(如果需要,您甚至可以将两种方式结合起来)。

  1. 如果您想让复合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" />
    
  2. 如果你想让复合ajax渲染一个组件 in 复合,那么让复合完成所有这些。

    <cc:interface>
        ...
    </cc:interface>
    <cc:implementation>
        <h:selectOneMenu ...>
            <f:selectItems ... />
            <p:ajax update="idOfComponentINSIDEComposite" />
        </h:selectOneMenu>
        <x:someComponent id="idOfComponentINSIDEComposite" />
    </cc:implementation>
    

    并以通常的方式使用它:

    <t:enum ... />