#{cc.clientId} evaluated in wrong composite after upgrading to JSF 2.2

血红的双手。 提交于 2019-12-02 02:04:37
BalusC

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.

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

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

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

    Which is to be used as:

    <t:enum ...>
        <p:ajax event="myCustomEventName" update=":absoluteClientIdOfComponentOUTSIDEComposite" />
    </t:enum>
    <x:someComponent id="idOfComponentOUTSIDEComposite" />
    
  2. 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 ... />
    
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!