Concatenating strings within EL expression defined in an attribute of a facelets tag - jsf

I need to write an EL expression for an attribute which goes something like this:
#{cc.attrs.appreciatedByCurrentUser ? (cc.attrs.count +'<br/>'+ (cc.attrs.count-1)) : ((cc.attrs.count+1) +'<br/>'+ cc.attrs.count)}
Now the problem is that this gives an error as strings cannot be concatenated, the way I am doing it. So how can I rectify this?
I'm using JSF 2.0 with facelets.
EDIT :
I'm resolving the issue using the following inline javascript
<script type="text/javascript">
var count=#{cc.attrs.count};
document.write(#{cc.attrs.appreciatedByCurrentUser} ? (count-1) +'<br/>'+count : count+'<br/>'+ (count+1));
</script>
Can you think of any issue with this?

It is possible to concatenate Strings in EL using the java.lang.String.concat(String) method. Thus your code could look like:
<h:outputText value="#{cc.attrs.appreciatedByCurrentUser ? (''.concat(cc.attrs.count).concat('<br/>').concat(cc.attrs.count-1)) : (''.concat((cc.attrs.count+1)).concat('<br/>').concat(cc.attrs.count))}" escape="false" />
In this particular case however I would go with one of the options that Mr BalusC had suggested because the code above doesn't look quite elegant. In some cases knowing this technique could be useful, though.
I would hardly recommend using javascript as a workaround here.

String concatenation in EL is only possible by just inlining in the expression. The + operator is in EL exclusively a sum operator. Further, < and > are invalid characters in XML attributes, so you have to escape them (and instruct <h:outputText> to not escape them once again by escape="false"):
<h:outputText value="#{cc.attrs.count}<br/>#{cc.attrs.count-1}" escape="false" rendered="#{cc.attrs.appreciatedByCurrentUser}" />
<h:outputText value="#{cc.attrs.count+1}<br/>#{cc.attrs.count}" escape="false" rendered="#{!cc.attrs.appreciatedByCurrentUser}" />
Alternatively, you can also use <c:set> to alias the expression:
<c:set var="appreciated" value="#{cc.attrs.count}<br/>#{cc.attrs.count-1}" />
<c:set var="notAppreciated" value="#{cc.attrs.count+1}<br/>#{cc.attrs.count}" />
<h:outputText value="#{cc.attrs.appreciatedByCurrentUser ? appreciated : notAppreciated}" escape="false" />

This is the only thing i can come up with.
<h:panelGroup rendered="#{cc.attrs.appreciatedByCurrentUser}">
<h:outputText value="#{(cc.attrs.count)}" style="display:block;" />
<h:outputText value="#{(cc.attrs.count-1)}" />
</h:panelGroup>
<h:panelGroup rendered="#{not cc.attrs.appreciatedByCurrentUser}">
<h:outputText value="#{(cc.attrs.count+1)}" style="display:block;" />
<h:outputText value="#{(cc.attrs.count)}" />
</h:panelGroup>
Putting <br> in a value attribute will always throw errors in JSF, so you'll have to use display:block.

Related

c:choose with multiple c:when - fall-through switch

If i have this code on my jsf page:
<c:choose>
<c:when test="${empty example1}">
</c:when>
<c:when test="${empty example2}">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>
it will work like java switch statement with case and break - if first when is true, second won't be test, right ?
What should i write to get "switch statement with case but without break" :
when first C:when is true something add to page and when second is true something is add to page too
You're thus basically looking for a fall-through switch. That isn't possible with <c:choose> as it represents a true if-else.... JSTL does not offer any tags for a fall-through switch.
Your best bet is to use multiple <c:if>s wherein you also check the preceding condition as an or condition.
<c:if test="#{empty example1}">
...
</c:if>
<c:if test="#{empty example1 or empty example2}">
...
</c:if>
<c:if test="#{empty example1 or empty example2 or empty example3}">
...
</c:if>
...
As you're using JSF, an alternative is using component's rendered attribute.
<h:panelGroup rendered="#{empty example1}">
...
</h:panelGroup>
<h:panelGroup rendered="#{empty example1 or empty example2}">
...
</h:panelGroup>
<h:panelGroup rendered="#{empty example1 or empty example2 or empty example3}">
...
</h:panelGroup>
...
The difference is that it's evaluated during view render time instead of during view build time. So if you were for example using this inside a <h:dataTable> based on the currently iterated row, the <c:if> wouldn't have worked the way you'd expect. See also JSTL in JSF2 Facelets... makes sense?
To eliminate the condition checking boilerplate, you could use <c:set> to create new EL variables. This works in both approaches.
<c:set var="show1" value="#{empty example1}" />
<c:set var="show2" value="#{show1 or empty example2}" />
<c:set var="show3" value="#{show2 or empty example3}" />
<h:panelGroup rendered="#{show1}">
...
</h:panelGroup>
<h:panelGroup rendered="#{show2}">
...
</h:panelGroup>
<h:panelGroup rendered="#{show3}">
...
</h:panelGroup>
...
I think it isn't possible with c:when. You can use c:if instead:
<c:if test="${empty example1}">
"example1 empty"
</c:if>
<c:if test="${empty example2}">
"example2 empty"
</c:if>
<c:if test="${not empty example1 and not empty example2}">
"both not empty"
</c:if>

Making h:outputtext don't print a line break on a jsf page

I have some code like the below and it works, but instead of showing just a number, I want to show "number%". Here's what I have:
<h:outputtext value="#{somebean.doubleValue}">
<f:convertnumber maxfractiondigits="2">
</h:outputtext>
If I put the "%" sign inside the value property, the converter won't work (I believe because the evaluated result is not just a number), but if I put the "%" sign in other outputtext tag, one line break appears between the number and it. I don't want that.
<h:outputtext value="#{somebean.doubleValue}">
<f:convertnumber maxfractiondigits="2">
</h:outputtext>
<h:outputtext value="%"> <!--prints a new line-->
What's the best way to achieve a "xx.xx%" formatting on jsf?
Set the CSS white-space property of the common parent element to nowrap.
E.g.
<span style="white-space: nowrap;">
<h:outputText value="#{somebean.doubleValue}">
<f:convertNumber maxfractiondigits="2">
</h:outputText>%
</span>
(note: you don't necessarily need <h:outputText> for plain text)
If you are actually using this in a <h:column> (as I would initially guess), you could specify a classname for the <td> by the columnClasses attribute of the <h:dataTable>.

Output curly brace in JSF h:outputText

I want to use the following EL inside a custom component:
<ui:param name="valueAfter"
value="#{not empty valueAfter ? valueAfter : false}" />
<h:outputText
value="#{x.label}#{valueAfter == true ? {x.value} : ''}" />
This does not work as I cannot output the curly braces around x.value but now I am looking for a good way to actually output those.
Try this:
<h:outputText value="#{x.label"}/>
<h:outputText value="{#{x.value}}" rendered="#{valueAfter}"/>
Here you go -In case you are using EL 2 (I think), one line with one h:outputText solution thanks to the .concat()
<h:outputText value="#{x.label}#{valueAfter == true?'{'.concat(x.value).concat('}'):''}" />

JSF: h:outputText; how to show a dash when the value is empty string?

I'm using h:outputText tags to display readonly data. Ex:
<h:outputText value="Phone Number:" />
<h:outputText value="#{userHandler.user.phoneNumber}" />
When "phoneNumber" is an empty string or a null, I want to display a dash "-" as the value.
Is there any easy way to do this maybe with expression language or something?
BTW, I thought about adding methods to the User class like getPhoneNumberDisplayText() that could do the check internally, but I since it's a view issue, I'd rather keep the code in the JSF page.
<h:outputText value="#{userHandler.user.phoneNumber != null
? userHandler.user.phoneNumber : '-'}" />
Or, you could make a new outputText:
<h:outputText rendered="#{userHandler.user.phoneNumber == null}" value="-" />

JSF Compound EL expression

I am trying to validate a inputText box based on the selection of a CheckBox as shown below.
< <h:inputText required="#{param[facesContext.externalContext.response.namespace'form:checkBoxId']}"> >.
The issue is as you see, the component Ids are dynamic, I should be able to use facesContext.externalContext.response.namespace inside the EL expression. Is there a solution to it, appreciate any suggestions.
Thanks.
Just bind the UIComponent to a page scoped property and access its getValue() method.
<h:selectBooleanCheckbox binding="#{checkbox}" />
<h:inputText required="#{not empty checkbox.value and checkbox.value}" />
As to the dynamicness, you can also go around by just giving it a fixed id.
<h:form id="form">
<h:selectBooleanCheckbox id="checkbox" />
<h:inputText required="#{not empty param['form:checkbox'] and param['form:checkbox']}" />
</h:form>
It's however only ugly when it gets lengthy.

Resources