Problem: I am passing an EL expression to a composite component, but the EL expression is being evaluated from inside the composite component, rather than before. The intention being that the EL expression evaluates to a string with is sent to the composite component.
I have a composite component, MenuTable
:
<cc:interface>
<cc:attribute name="model" type="nz.co.tradeintel.web.MenuTable"/>
<cc.attribute name="updateId" />
</cc:interface>
<cc:implementation>
<h:panelGroup id="menuTable">
<table>
<ui:repeat id="repeat1" value="#{cc.attrs.model.rows}" var="row">
<tr>
<ui:repeat id="repeat2" value="#{row.contents}" var="entry">
<td>
<p:commandLink action="#{cc.attrs.model.setSelected(entry)}" update="#{cc.attrs.updateId}" value="#{entry.toString()}"/>
</td>
</ui:repeat>
</tr>
</ui:repeat>
</table>
</h:panelGroup>
</cc:implementation>
The intention is that I pass an absolute component ID as the attribute updateId
like this:
<p:PanelGroup id="updatingPanel">
<!-- Lots of components.-->
</p:PanelGroup>
<custom:MenuTable updateId="#{component.clientId}:updatingPanel" model="#{menuBackBean.menuTable}" />
The problem is, the EL expression for the updateId
is evaluated from the scope of the <p:commandLink />
within the composite component, and I get the following error:
javax.faces.FacesException: Cannot find component with identifier ":j_idt37:j_idt39:updatingPanel:j_idt61:repeat1:0:repeat2:0:j_idt65:updatingPanel" referenced from "j_idt37:j_idt39:updatingPanel:j_idt61:repeat1:0:repeat2:0:j_idt65".
Note: JSF thinks I am trying to update a component with and ID of updatingPanel
which is inside the composite component.
Why is the EL expression not evaluated from the outer scope: <custom:MenuTable/>
?
There are a few related answers, but I don't understand them, such as this one.
Using Mojarra 2.1.15
EL expressions are not evaluated at the moment the component is built, but at the moment the attribute is accessed. In other words, they're runtime and not buildtime. The
#{component}
refers to the current UI component at the moment the EL expression is evaluated, which is in your particular case the<p:commandLink>
. That explains the different outcome.You need to approach this differently, without using
#{component}
. One of the ways isIf that still doesn't work, then make sure that you don't use
<h:form prependId="false">
.See also: