EL conditional render based on composite component attribute [duplicate] - jsf

I'm using an <h:outputLink> as follows.
<c:set var="cid" value="1"/>
<c:set var="sid" value="2"/>
<h:outputLink value="Test.jsf">
<h:outputText value="Link"/>
<f:param name="cid" value="#{cid}"/>
<f:param name="sid" value="#{sid}"/>
</h:outputLink>
This is just an example. Both of the query-string parameters are dynamic. So, <c:set> used here is just for the sake of demonstration.
At any time, either one, both or none of the parameters may be present. In case, if only one or none of them is present then, parameter/s are unnecessarily appended to the URL which should not happen. Preventing unnecessary query-string parameters from being appended to the URL requires a conditional rendering of <f:param>.
JSTL <c:if> like the following
<c:if test="${not empty cid}">
<f:param name="cid" value="#{cid}"/>
</c:if>
did not work.
How can it be made possible to conditionally render <f:param> inside <h:outputLink>?

The <f:param> has a disable (not disabled!) attribute for the purpose.
<f:param name="cid" value="#{cid}" disable="#{empty cid}" />
<f:param name="sid" value="#{sid}" disable="#{empty sid}" />
Note that this has a bug in Mojarra versions older than 2.1.15, because they typo'ed the actual UIParameter property to be disble instead of disable. See also issue 2312.
As to the <c:if> approach, that would only work if the #{cid} and #{sid} is available during view build time. In other words, it would fail if they are only available during view render time, e.g. when they depend on var of a repeater component. See also JSTL in JSF2 Facelets... makes sense?
See also:
f:param tag attribute 'disable' is not work

Don't you like this kind of a solution?
<f:param name="#{cid == null ? '' : 'cid'}" value="#{cid}"/>
<f:param name="#{sid == null ? '' : 'sid'}" value="#{sid}"/>

Related

Conditionally render a <div> based on value of <h:outputText>

I am using jsf primefaces. I want to display an image depending on the value of a specific outputext. If the text value is 'Alarm *' then a div will appear whith a spesific image. If the value is 'Alarm **' then a div with an other image will appear, etc. I tried the code below but it does not work for me.
<h:outputText id="alarmCriticalityValue" value="#{msg[summary.criticality.key]}" />
<c:if test="#{alarmCriticalityValue=='Alarm *'}">
<div class="alarm1"></div>
</c:if>
How should i implement this idea?
You need to use binding attribute to put the UIComponent instance in the EL scope. The id attribute doesn't do that, on contrary to what you expected.
<h:outputText binding="#{alarmCriticality}" ... />
And then you need to use UIOutput#getValue() to obtain its value attribute.
<c:if test="#{alarmCriticality.value == 'Alarm *'}">
That said, you'd better use rendered attribute here, particularly if #{summary} represents the currently iterated item of a JSF iterating component like <ui:repeat> or <h:dataTable>.
<h:panelGroup layout="block" styleClass="alarm1"
rendered="#{alarmCriticality.value == 'Alarm *'}" />
See also:
How does the 'binding' attribute work in JSF? When and how should it be used?
How to conditionally render plain HTML elements like <div>s?
JSTL in JSF2 Facelets... makes sense?
Unrelated to the concrete problem. It's strange to see the conditional rendering depend on localized text. What if you change the locale and/or the localized text? This is very brittle. You'd better check the bundle key instead.
<h:outputText value="#{msg[summary.criticality.key]}" />
<h:panelGroup layout="block" styleClass="alarm1"
rendered="#{summary.criticality.key == 'some.alarm.key'}" />
This way you also don't need to bind the output text anymore.
Try
<c:if test="#{msg[summary.criticality.key].equals('Alarm *')}">
Or add a binding to the h:outputText and check against that.
Try this
<h:outputText id="alarmCriticalityValue" value="#{msg[summary.criticality.key]}" />
<h:panelGroup layout="block" styleClass="alarm1" rendered="#{alarmCriticality.value eq 'Alarm *'}" />

Conditional rendering of f:param in JSF

I'm using an <h:outputLink> as follows.
<c:set var="cid" value="1"/>
<c:set var="sid" value="2"/>
<h:outputLink value="Test.jsf">
<h:outputText value="Link"/>
<f:param name="cid" value="#{cid}"/>
<f:param name="sid" value="#{sid}"/>
</h:outputLink>
This is just an example. Both of the query-string parameters are dynamic. So, <c:set> used here is just for the sake of demonstration.
At any time, either one, both or none of the parameters may be present. In case, if only one or none of them is present then, parameter/s are unnecessarily appended to the URL which should not happen. Preventing unnecessary query-string parameters from being appended to the URL requires a conditional rendering of <f:param>.
JSTL <c:if> like the following
<c:if test="${not empty cid}">
<f:param name="cid" value="#{cid}"/>
</c:if>
did not work.
How can it be made possible to conditionally render <f:param> inside <h:outputLink>?
The <f:param> has a disable (not disabled!) attribute for the purpose.
<f:param name="cid" value="#{cid}" disable="#{empty cid}" />
<f:param name="sid" value="#{sid}" disable="#{empty sid}" />
Note that this has a bug in Mojarra versions older than 2.1.15, because they typo'ed the actual UIParameter property to be disble instead of disable. See also issue 2312.
As to the <c:if> approach, that would only work if the #{cid} and #{sid} is available during view build time. In other words, it would fail if they are only available during view render time, e.g. when they depend on var of a repeater component. See also JSTL in JSF2 Facelets... makes sense?
See also:
f:param tag attribute 'disable' is not work
Don't you like this kind of a solution?
<f:param name="#{cid == null ? '' : 'cid'}" value="#{cid}"/>
<f:param name="#{sid == null ? '' : 'sid'}" value="#{sid}"/>

How to do conditional update on a component

I have a JSF composite component which renders only some parts based on the attribute cc.attrs.list passed to it.
In one of the components I want to update a set of other components based on the attribute. So something like this:
<p:ajax event="dialogReturn" listener="#{cc.listener}"
update="#{cc.attrs.id2}_input #{cc.attrs.id2}_resultTable"/>
The problem is that the resultTable is not rendered all the time and when the resultTable is not there, I get an exception Cannot find component with expression "id_resultTable", which is not surprising. So my idea was to create a variable which will contain id of the attribute or empty String like this:
<c:if test="#{cc.attrs.list}">
<ui:param name="updateTable" value="#{cc.attrs.id2}_resultTable"/>
</c:if>
<c:otherwise>
<ui:param name="updateTable" value=""/>
</c:otherwise>
and then do the ajax update like this:
<p:ajax event="dialogReturn" listener="#{cc.listener}"
update="#{cc.attrs.id2}_input #{updateTable}"/>
The problem is, that the #{updateTable} variable is always an empty String(I've tried to put it as a content of outputText) and I have no idea why.
You can just omit the ui:param and do the check directly in the p:ajax:
<p:ajax event="dialogReturn" listener="#{cc.listener}"
update="#{cc.attrs.id2}_input #{cc.attrs.list ? cc.attrs.id2.concat('_resultTable') : ''}"/>
A problem with the c:if-approach could be, that when you update this section via ajax the condition is not re-checked as JSTL-tags are evaluated at view build time. Have a look at JSTL in JSF2 Facelets... makes sense? for further information.
This is not really a solution, but I've done a workaround for the problem which works. I've added h:panelGroup with id around the table and I'm updating this instead of the table.

`h:commandLink` action is not invoked ( maybe because of `ui:repeat`)

Here is code:
<ui:repeat var="entity" varStatus="status" value="#{myentityListView.someList}">
<h:form>
<h:commandLink value="Go!" action="mypage.xhtml" >
<c:if test="#{entity.entityType=='Comment'}"><f:param name="productId" value="#{entity.product.getId()}"/></c:if>
<f:param name="userId" value="#{entity.user.getId()}"/>
</h:commandLink>
</h:form>
</ui:repeat>
Maybe its cause is that h:commandLink is in ui:repeat.
mypage.xhtml is an exixting page.
Thanks
You need to make sure that #{myentityListView.someList} returns exactly the same value during the form submit request as it was during the request of displaying the page. Putting the bean in the view scope (just mark it #ViewScoped) and ensuring that you preserve the list during (post)constructor or in an action method should fix it.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated
However, in your particular case, it's much better to just use <h:link> instead as you don't seem to need to send a POST request at all. This way you end up with nice bookmarkable and searchbot-chipherable links.
<ui:repeat var="entity" varStatus="status" value="#{myentityListView.someList}">
<h:form>
<h:link value="Go!" outcome="mypage.xhtml">
<f:param name="userId" value="#{entity.user.id}" />
<f:param name="productId" value="#{entity.product.id}" disable="#{entity.entityType != 'Comment'}" />
</h:link>
</h:form>
</ui:repeat>
Also note that I fixed your <c:if> approach by removing it as it won't work as you'd expect. It would always evaluate false. See also JSTL in JSF2 Facelets... makes sense?
See also:
When should I use h:outputLink instead of h:commandLink?

f:param tag attribute 'disable' is not work

I try to use <f:param> tag to build output link URL with parameters depending on some my conditions.
When I place this tag inside h:output link and try to set different values for 'disable' I see no effect.
Here the my code
<h:outputLink value="/WebApplication10/faces/index.xhtml">
Link1
<f:param disable="#{true}" name="name1" value="value1"/>
<f:param disable="#{false}" name="name2" value="value2"/>
</h:outputLink>
I expect to see only one param in url but I see both.
Using disable="true" instead of disable="#{true}" works for me.
So, it's either a bug in the tag documentation that it supports ValueExpression or a bug in the UIParameter class that it does not resolve it as a ValueExpression. I have at least reported issue 2102 for this.
Update: As a temporary hack/workaround, you could use <c:if> to control the inclusion of the <f:param> tag during view build time.
<h:outputLink value="/WebApplication10/faces/index.xhtml">
Link1
<c:if test="#{!true}"><f:param name="name1" value="value1"/></c:if>
<c:if test="#{!false}"><f:param name="name2" value="value2"/></c:if>
</h:outputLink>
Note that this is not going to work when this piece is embedded in a JSF iterated component such as <ui:repeat>, <h:dataTable> and on and the test condition depends on the iterated variable.
Use 'disble' instead 'disable'.
The reason is described here:
http://markmail.org/message/bmb2lek5mcx4ofp7

Resources