ICEfaces
  1. ICEfaces
  2. ICE-8231

Component handling of "for" attributes is not portlet-friendly

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Labels:
      None
    • Environment:
      All

      Description

      During investigation into ICE-7955, I saw that the handling of the "for" attribute is generated from boilerplate code in our code generation framework. Paraphrasing from that previous JIRA:

      Looking at the TabSetProxy as an example, it extends TabSetProxyBase which is a generated class. It generates code to handle the getFor and setFor methods. In this case it uses some generic, boilerplate code to store the value of the 'for' attribute and look it up again. However, this doesn't take into consideration that the base id provided in the markup:

                  <ace:tabSet id="myTabSet" cancelOnInvalid="#{not tabProxy.invalidSwitch}" clientSide="false">
                      <ace:tabPane id="txtEntry">
                          <f:facet name="label">Text Entry</f:facet>
                          <h:form id="proxyForm">
                              <ace:tabSetProxy for="myTabSet"/>


      won't necessarily be the same as the client id that ends up getting rendered out for the actual component. For example when running as a portlet, the client id of the tabset ends up being namespace by the portlet bridge:

      PortletFaces Bridge: "A6150:myTabSet"
      Liferay Faces Bridge: "_jpfcpncuivr_A6150_j_id1:myTabSet"

      What I ended up doing in ICE-7955 was overriding the getFor method in TabSetProxy to do a lookup of the actual component using the supplied id and then getting the client id of that TabSet. This is similar to what I saw happens internally for Mojarra in the LabelRenderer:

          @Override
          public String getFor() {
              //Get the originally stored value
              String forComponentId = super.getFor();
               
              //Proceed to find the component that it belongs to using one of our existing find methods
              UIViewRoot root = getFacesContext().getViewRoot();
              UIComponent forComponent = CoreComponentUtils.findComponentInView(root, forComponentId);
              if( forComponent != null ){
                  //Get the client id of the found component and use that
                  forComponentId = forComponent.getClientId();
              }
              return forComponentId;
          }

      Assuming the component can be reliably found this way, the resulting hidden inputText value now matches the actual id of the tabset:

      <input id="A6150:myTabSet_tsc" name="A6150:myTabSet_tsc" type="hidden">

      We may have similar issues with other components that use the same generated code for handling the "for" attribute. A quick count from my IDE shows that there are potentially a number (17) of compat (10) and ACE (7) components that may need to be fixed in a similar fashion.

        Activity

        There are no comments yet on this issue.

          People

          • Assignee:
            Unassigned
            Reporter:
            Deryk Sinotte
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated: