Excuse the basic question, I'm crash-coursing myself on Java/JSTL to fix an issue for a client and have not been able to quickly find the answer to something I'm dealing with....
I have a JSP page which uses the <c:if> tag to compare a variable to the constant value of 0. This is always returning False for me. I.e.
<c:set var="total" value="0" />
<c:forEach items="${parentItem.children}" var="child">
<c:set var="total" value="${total+child.revenue}" />
<c:if test="${total == 0}">
It is zero.
</c:if>
</c:forEach>
From my understanding, I have to explicitly compare like-types, however when attempting to do something like this, I get an error:
<c:if test="${total.compareTo(BigDecimal.ZERO) == 0}">
-
</c:if>
The error is: The function compareTo must be used with a prefix when a default namespace is not specified.
I'm using JSTL 1.2.
Related
This question already has answers here:
c:choose not working in JSF
(2 answers)
Closed 8 years ago.
I'm trying to create a table, where when the "key" is equal to "name", the value is a link to another page otherwise it should print the value as text.I have the following keys: [name, category, schema]. It's an ArrayList
<c:when test='#{(results.keys.get(loopVal.index)).equals("name")}'>
In my table the column "name" should have values as a link. But it doesn't work, as if the c:when returns false. But i checked "results.keys.get(loopVal.index)" and it prints the keys correctly.
I have tried comparing with equals(), with ==, and eq. I also have the correct jstl library xmlns:c="http://java.sun.com/jsp/jstl/core"
I can't find the problem, maybe it has something to do with comparing a list element? or am I overlooking something really obvious?
Here is a larger snippet of my code:
<ui:repeat value="#{results.keys}" var="key" varStatus="loopVal">
<td id="#{results.keys.get(loopVal.index)}_#{instance.getId()}" class="view">
<c:choose>
<c:when test='#{(results.keys.get(loopVal.index)).equals("name")}'>
<h:link value="#{values.get(loopVal.index)}" outcome="search">
<f:param name="type" value="#{values.get(loopVal.index)}" />
</h:link>
</c:when>
<c:otherwise>
#{values.get(loopVal.index)}
</c:otherwise>
</c:choose>
</td>
</ui:repeat>
You should use c:forEach instead of ui:repeat:
<c:forEach items="#{results.keys}" var="key" varStatus="loopVal">
...
</c:forEach>
Have a look at this post by BalusC about the difference between tag handlers (like c:forEach) and normal JSF components (like ui:repeat).
I am using the following code to compare two variables, but it seems it has an error as the page does not get loaded at all.
Based on this answer my code should be correct but surprisingly does not work.
If I remove the <c:when> line it shows
the values of ${name} and ${myvar.employee.name}.
<c:forEach var="myvar" items="${user.names}">
${name}
${myvar.employee.name}
<c:when test="${name eq myvar.employee.name}">
hello
</c:when>
The structure with <c:when> requires <c:choose>
<c:choose>
<c:when test="${your condition here}">
</c:when>
<c:otherwise>
</c:otherwise>
</c:choose>
otherwise you will get error.
As Alex has pointed out, you cannot have non-wrapped <c:when> in your code.
But it looks like, in your case, <c:choose> is not required, because you have only a single clause. In this case <c:if> may be a better option:
<c:if test="${name eq myvar.employee.name}">
hello
</c:if>
I have a JSTL loop where I'm trying to check to see if a given variable is empty or not with a dynamic variable name. When I use c:set with page scope, the variable is not accessible to the if statement. However, when I set it using <% pageCotnext.setAttribute(...); %>, the variable is available.
<%
pageContext.setAttribute("alphaParA", "test");
pageContext.setAttribute("alphaParF", "test");
int i = 0;
%>
<ul class="alphadex_links">
<c:forEach var="i" begin="0" end="25" step="1" varStatus="status">
<c:set var="currentLetter" scope="page">&#${i+65}</c:set>
<c:set var="currentPar" scope="page">alphaPar${currentLetter}</c:set>
<% pageContext.setAttribute("currentPar", "alphaPar" + (char)('A' + i++)); %>
<li>
<c:choose>
<c:when test="${not empty pageScope[currentPar]}">
The test is always fails when I remove the pageContext.setAttribute block, however it succeeds for A and F as it should when the block is in. I'm very confused and can't find help anywhere.
It fails because HTML doesn't run at the moment JSTL runs. You're effectively passing a Java String A to it instead of the desired character A which would be represented as such based on the HTML entity A when the HTML is retrieved and parsed by the webbrowser after Java/JSP/JSTL has done its job. Please note that your HTML entity is missing the closing semicolon, but this isn't the cause of your concrete problem.
As to the concrete functional requirement, sorry, you're out of luck with EL. It doesn't support char. Your best bet is to deal with strings like this:
<c:forEach items="${fn:split('A,B,C,D,E,F,G,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z', ',')}" var="currentLetter">
<c:set var="currentPar" value="alphaPar${currentLetter}" />
${pageScope[currentPar]}
</c:forEach>
If necessary, just autogenerate the letters as String[] in Java end and set it as application attribute.
This question already has answers here:
instanceof check in EL expression language
(7 answers)
Closed 2 years ago.
I'm using JSTL and want to check whether an object is a String or a Collection.
fn:length returns results on both types (stringsize or number of elements in the collection).
<c:if test="${fn:length(item)>1}">
<c:out value="${fn:length(item)} " />
</c:if>
How can I determine which one I've got?
You could look at the class name. For example:
<c:if test="${item.class.simpleName == 'String'}">
<!-- it's a String! -->
</c:if>
item.class lead to errors when using with tomcat 7.
For me this works (although it's dirtier):
${item.link.getClass().simpleName == 'String'}
If you need to distinguish whether something is a Collection or not, you can use iteration to find out if it's a Collection, and set a var. This worked for me:
<c:set var="collection" value="false" />
<c:forEach var="item" items="${yourObjectWhichMayBeCollection}" varStatus="row">
<c:if test="${row.index > 0}">
<c:set var="collection" value="true" />
</c:if>
</c:forEach>
<!--Now you can examine ${collection} & decide e.g. Collection vs. String -->
How can I loop through each character in a String using JSTL?
Tricky use of fn:substring() would do
<c:forEach var="i" begin="0" end="${fn:length(str)}" step="1">
<c:out value="${fn:substring(str, i, i + 1)}" />
</c:forEach>
Late to the party, but EL 2.2 allows for instance method calls (more on that here: https://stackoverflow.com/a/7122669/2047962). This means that you could shorten Jigar Joshi's answer by a few characters:
<c:forEach var="i" begin="0" end="${fn:length(str)}" step="1">
<c:out value="${str.charAt(i)}" />
</c:forEach>
I only suggest this because it is a little more obvious what your code is doing.
i think you can't do that with JSTL's forEach. You need to write your own tag or an EL function. Here is a sample code how you write your custom tags:
http://www.java2s.com/Tutorial/Java/0360__JSP/CustomTagSupport.htm