Details
-
Type:
Bug
-
Status: Open
-
Priority:
Major
-
Resolution: Unresolved
-
Affects Version/s: None
-
Fix Version/s: None
-
Component/s: ACE-Components, ICE-Components
-
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 inICE-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.
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
@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
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion
Field | Original Value | New Value |
---|---|---|
Salesforce Case | [] | |
Assignee | Ken Fyten [ ken.fyten ] |
Assignee | Ken Fyten [ ken.fyten ] |