I have a List of beans, each of which has a property which itself is a List of email addresses.
<c:forEach items="${upcomingSchedule}" var="conf">
<div class='scheduled' title="${conf.subject}" id="scheduled<c:out value="${conf.id}"/>">
...
</div>
</c:forEach>
This renders one <div>
per bean in the List.
For the sublist, what I'd like to be able to do is to concatenate each of the entries in the list to form a single String, to be displayed as a part of the <div>
's title
attribute. Why? Because we are using a javascript library (mootools) to turn this <div>
into a floating tool tip, and the library turns the title
into the text of the tooltip.
So, if ${conf.subject}
was "Subject", ultimately I'd like the title
of the <div>
to be "Subject: [email protected], [email protected], etc.", containing all of the email addresses of the sub-list.
How can I do this using JSP EL? I'm trying to stay away from putting scriptlet blocks in the jsp file.
The + operator always means numerical addition in JSP Expression Language. To do string concatenation you would have to use multiple adjacent EL expressions like ${str1}${str2} .
Using the + operator is the most common way to concatenate two strings in Java. You can provide either a variable, a number, or a String literal (which is always surrounded by double quotes). Be sure to add a space so that when the combined string is printed, its words are separated properly.
The last method includes concatenating the boolean and Boolean values to a string. It is a simple trick which joins the string and boolean values to return a new string. As shown in the example below, we have concatenated a and b with two strings, c and d , which resulted in a new string displayed in the output.
The "clean" way to do this would be to use a function. As the JSTL join
function won't work on a Collection
, you can write your own without too much trouble, and reuse it all over the place instead of cut-and-pasting a large chunk of loop code.
You need the function implementation, and a TLD to let your web application know where to find it. Put these together in a JAR and drop it into your WEB-INF/lib directory.
Here's an outline:
com/x/taglib/core/StringUtil.java
package com.x.taglib.core;
public class StringUtil {
public static String join(Iterable<?> elements, CharSequence separator) {
StringBuilder buf = new StringBuilder();
if (elements != null) {
if (separator == null)
separator = " ";
for (Object o : elements) {
if (buf.length() > 0)
buf.append(separator);
buf.append(o);
}
}
return buf.toString();
}
}
META-INF/x-c.tld:
<taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0">
<tlib-version>1.0</tlib-version>
<short-name>x-c</short-name>
<uri>http://dev.x.com/taglib/core/1.0</uri>
<function>
<description>Join elements of an Iterable into a string.</description>
<display-name>Join</display-name>
<name>join</name>
<function-class>com.x.taglib.core.StringUtil</function-class>
<function-signature>java.lang.String join(java.lang.Iterable, java.lang.CharSequence)</function-signature>
</function>
</taglib>
While the TLD is a little verbose, knowing your way around one is a good skill for any developer working with JSP. And, since you've chosen a standard like JSP for presentation, there's a good chance you have tools that will help you out.
This approach has many advantages over the alternative of adding more methods to the underlying model. This function can be written once, and reused in any project. It works with a closed-source, third-party library. Different delimiters can be supported in different contexts, without polluting a model API with a new method for each.
Most importantly, it supports a separation of view and model-controller development roles. Tasks in these two areas are often performed by different people at different times. Maintaining a loose coupling between these layers minimizes complexity and maintenance costs. When even a trivial change like using a different delimiter in the presentation requires a programmer to modify a library, you have a very expensive and cumbersome system.
The StringUtil
class is the same whether its exposed as a EL function or not. The only "extra" necessary is the TLD, which is trivial; a tool could easily generate it.
Figured out a somewhat dirty way to do this:
<c:forEach items="${upcomingSchedule}" var="conf">
<c:set var="title" value="${conf.subject}: "/>
<c:forEach items="${conf.invitees}" var="invitee">
<c:set var="title" value="${title} ${invitee}, "/>
</c:forEach>
<div class='scheduled' title="${title}" id="scheduled<c:out value="${conf.id}"/>">
...
</div>
</c:forEach>
I just use <c:set>
repeatedly, referencing it's own value, to append/concatenate the strings.
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