I'm developing a web application with JSF 2.0 (mojarra) + primefaces. In the past I successfully used the [c:set] tag of jstl library to store some temporary data or output form other tags.
In my current case I want to use that again but it doesn't work properly and I have no idea why. In the follow example it works but particularly. Why does the case 2 not work properly?
<h:form id="userAdministration">
<p:messages id="messages" showDetail="true" />
<p:dataTable id="userTable" selectionMode="single" var="user" value="#{users}">
<p:column>
<f:facet name="header">
<h:outputText value="#{message.user_table_header_id_column}" />
</f:facet>
<h:outputText value="#{user.id}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="#{message.global_table_header_action_column}" />
</f:facet>
<p:commandButton type="push" onclick="#{user.loginname}DeleteConfirmation.show()" value="#{message.global_table_action_delete}" image="ui-icon-trash">
<f:setPropertyActionListener value="#{user}" target="#{userAdministrationController.selectedUser}" />
</p:commandButton>
<!-- 1. WORKS FINE, STORED VALUE IS "loginname" -->
<c:set var="deleteConfirmationMessage" value="#{user.loginname}"></c:set>
<!-- 2. VALUE IS "!!!" AND NOT "loginname !!!" -->
<c:set var="deleteConfirmationMessage2">
<h:outputText value="#{user.loginname}" />!!!
</c:set>
<!-- 3. WORKS FINE (OUTPUT "loginname") -->
<h:outputText value="#{user.loginname}" />
<p:confirmDialog message="#{deleteConfirmationMessage}" header="#{message.user_dialog_delete_confirmation_title}" severity="alert" widgetVar="#{user.loginname}DeleteConfirmation">
<p:commandButton value="#{message.user_dialog_delete_confirmation_no}" onclick="#{user.loginname}DeleteConfirmation.hide()" update="@form" type="button" />
</p:confirmDialog>
</p:column>
Why does the case 2 not work properly?
<!-- 2. VALUE IS "!!!" AND NOT "loginname !!!" --> <c:set var="deleteConfirmationMessage2"> <h:outputText value="#{user.loginname}" />!!! </c:set>
That's because taghandlers and UI components doesn't run at the same time. JSTL tags are taghandlers and they run during building the view (when the XHTML file is converted to JSF component tree). JSF <h:xxx>
tags are UI components and they run during rendering the view (when the JSF component tree is converted/rendered to HTML code). See also JSTL in JSF2 Facelets... makes sense?
So, when the <c:set>
runs, the <h:outputText>
hasn't run at all.
But in this particular construct you actually don't need the <h:outputText>
at all. Apart from setting it as value
of <c:set>
, you could also just inline the EL expression raw in the template text (note that this works when using JSF with Facelets, not when using JSF with JSP; given the fact that you're using PrimeFaces, you're definitely using Facelets as PrimeFaces doesn't have a JSP taglib at all).
<c:set var="deleteConfirmationMessage2">
#{user.loginname}!!!
</c:set>
or perhaps you weren't aware that you can mix EL and plain strings in an attribute like
<c:set var="deleteConfirmationMessage2" value="#{user.loginname}!!!" />
or
<p:confirmDialog message="#{user.loginname}!!!">
Depending on the concrete functional requirement, which isn't exactly clear from the question, a different alternative may be to use the <o:cache>
component of OmniFaces. This may be more useful if you intend to cache the value for a broader scope than just the page/request scope like as in your <c:set>
examples.
Just making an educated guess, because I haven't tried to combine JSF and JSTL, but I believe the c:set would be handled before the h:outputText is rendered, so it would only see the static text in its body. I'm not sure what order tag handlers are called in relation to the JSF lifecycle but putting in some logging would clear that up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With