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

前端 未结 1 685
粉色の甜心
粉色の甜心 2021-01-22 00:04

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 t

相关标签:
1条回答
  • 2021-01-22 00:36

    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 ... />
      
    0 讨论(0)
提交回复
热议问题