iterating of muliple items in jstl - jstl

I have this requirement to iterate over 3 lists at the same time in jstl. for iterating over a single list we use
<c:forEach var = "mfgn" items = "${requestScope.mfgNumber}" varStatus = "status">
do something;
</c:forEach>
I need to do some thing like
<c:forEach var = "mfgn" var = "issue" items = "${requestScope.mfgNumber}" items = "${requestScope.something" varStatus = "status">
mfgNumber;
</c:forEach>
is this possible or there an otherway to iterate over multiple lists at the same time.

If they have the same size, then there are two options, assuming that it are List<Integer> and List<String>:
Merge them in a single list with entities which in turn repesents the items of each other list in a single class like List<ManfacturerIssue> where the ManfacturerIssue is a javabean class which contains Integer number and String issue properties. This way you can end up doing:
<c:forEach items="${mfgIssues}" var="mfgIssue">
${mfgIssue.number}, ${mfgIssue.issue}
</c:forEach>
Iterate by index instead, this is however ugly and unmaintainable as (fill in):
<c:forEach begin="0" end="${fn:length(mfgNumbers) - 1}" varStatus="loop">
${mfgNumbers[loop.index]}, ${issues[loop.index]}
</c:forEach>

Related

Concatenate two variables to check null condition using JSTL tags

I am trying to send image of each user separately in ModelMap
model.addAttribute("profileImage"+i, sb); // I have added attribute in loop
Variable 'i' is an index for each image which I am iterating for each user.
Now I am Having profileImage0,profileImage1,profileImage2 and so on.
While Accessing I am putting some condition
<c:choose>
<c:when test="${profileImage!=null}">
<center><img src="${profileImage}" id="${profileImage}" class="rounded-circle img-circle img-responsive" style="height:90px;width:90px;" alt="Avatar">
</c:when>
<c:otherwise>
<center><img src="${pageContext.request.contextPath}/resources/images/defaultuserprofile.png" id="${profileImage}" class="rounded-circle img-circle img-responsive" style="height:90px;width:90px;" alt="Avatar"></center>
</c:otherwise>
</c:choose>
So in the Above Code I need to append some indexing to a variable which will first initialize the value of a variable then use it properly instead using like this one.
like profileImage0,profileImage1 and so on....
You can make use of the <c:forEach> tag to iterate over your variables. You may want to pass in the maximum number of values you have in your controller so you know how many values you need to pick up from your request:
<c:forEach var = "i" begin = "1" end = "${max}">
<c:set var = "variableName" scope = "session" value = "profileName + ${i}"/>
<c:set var = "profileImage" scope = "session" value = "${variableName}"/>
</c:forEach>
(or something like that...)

can i use one <c:forEach> inside another <c:forEach>

<c:forEach var="expData" items="${expenseDataList}">
<tr>
<td>
<div class="custom-control custom-checkbox">
<label><aui:input
cssClass="custom-control-input expense select-all"
type="checkbox" data-amount="${expData.expenseAmount}" data-expenseid="${expData.expenseId}"
id="expenseCheckbox" name="expenseCheckbox" label="" />
</label>
</div>
</td>
....
<td>
<c:forEach var="previewUrl1" items="${previewUrl}">
<aui:button icon=" icon-download-alt"
style="border:none; background-color: #1E47C2; color:white"
data-previewurl="${previewUrl1}" cssClass="download"
name="downloadButton" id="downloadButton" />
</c:forEach>
</td>
</tr>
</c:forEach>
I am using inside and It is creating 2 download button because I am iterating another near to download button.. I am getting the value inside previewUrl1 but it is creating 2 button as it is iterating twice because inside another
This is my portlet side code
long fileEntryId = 0L;
String previewURL = StringPool.BLANK;
List<String> s1=new ArrayList<String>();
try {
for (int i = 0; i < expenseDataList.size(); i++) {
fileEntryId = expenseDataList.get(i).getFileEntryId();
if (fileEntryId > 0) {
FileEntry fileEntry = DLAppLocalServiceUtil.getFileEntry(fileEntryId);
previewURL = DLUtil.getPreviewURL(fileEntry, fileEntry.getFileVersion(), themeDisplay, StringPool.BLANK);
}
renderRequest.setAttribute("previewUrl", previewURL);
s1.add(previewURL);
LOG.info("File Entries"+fileEntryId);
LOG.info("Preview URl " + previewURL);
}
LOG.info(s1);
renderRequest.setAttribute("previewUrl", s1);
} catch (Exception e) {
e.printStackTrace();
}
I don't fully understand your description of what happens. But in case there are multiple iterations of your inner loop, you're generating repeated id attributes in two cases: In your outer loop for the aui:input, in your inner loop for the aui:button. According to the HTML rules, the id must be unique, or you'll get undefined behavior (or every element but the first one being ignored)
Edit:
In your code, you use renderRequest.setAttribute("previewUrl", previewURL);, e.g. you set exactly one previewURL. Later, you change that attribute to a list, through renderRequest.setAttribute("previewUrl", s1); - don't do that: It makes your code unmaintainable and tricks readers (like me or others here) into thinking that previewURL is a single value when indeed it's list.
That being said: It seems that you have two lists with the same number of entries, and each element in one list refers to the element with the same index in the other list. And if you nest those lists, you'll naturally show all elements of list 2 for each element of list 1. Thus: Don't nest loops. You'll need only one loop, and access the corresponding element from the other loop directly by index.
I don't have JSTL in my muscle memory: Within the remaining (outer) forEach, keep track of the index (through varStatus, see this question on how to do it) and use this index to access the matching element in your second list.

jstl access a second array value with foreach index

i have two arrays (strings delimited with commas) and i made a foreach loop on one of this vars
i need to be able to access to the other string with the foreach index like
<c:set var="name" value="Zara,nuha,roshy" />
<c:set var="name2" value="Zara2,nuha2,roshy2" />
<c:forEach items="${name}" delims="," var="name" varstatus="i">
<c:out value="${name}"/><br>
</c:forEach>
i need to access name2 values, in the name foreach, is it possible without doing another foeach?
The varstatus variable you are using contains a value "index" that you can use.
But, you can't operate on a string like that (not that I know of at least).
First, you need to convert name2 to a proper array or list. Then you can access it inside the for loop:
${name2list[i.index]}
Now, how to convert it to an array? How about the split function?
<%#taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="name2list" value="${fn:split(name2, ',')}"/>
This can be done, contrary to some previous comments.
See the following example based on the question:
<c:set var="names" value="Zara,nuha,roshy" />
<c:set var="names2" value="Zara2,nuha2,roshy2" />
<c:forEach items="${names.split(',')}" varStatus="i" var="name" >
${name} : ${names2.split(',')[i.index]}<br/>
</c:forEach>
Essentially we're using a string split function with expression language to get a string array from list comma separated values. Within the loop we the get the second value from the names2 array by using the varStatus index. I believe this accomplishes the task.

set value of jquery variable equal to a jstl variable

I have a jstl value,
<c:forEach items="${detail}" var="u">
<c:set value="${u.content}" var="c"/></c:forEach>
I want to set the variable in jquery equal to the var = "c".
How could I do that?
<script>
<c:forEach items="${detail}" var="u">
<c:set value="${u.content}" var="c"/>
var whatever = ${c};
</c:forEach>
<script>
You might need to JS escape it, quote it, etc. depending on what's actually in the variable, which you don't mention. It's also not clear what "a variable in jQuery" is.
The bottom line is that if the JavaScript lives in a JSP, just use the value: the JS isn't evaluated until the response has been emitted, so mix-and-match, but be aware that it's pretty easy to create invalid JavaScript unless you take care to properly escape whatever value types you're emitting.
As an example, consider a Java String that contains a single quote: if you single-quote the Java value in JS you'd have invalid JS because you didn't JS-escape the string value.
the method given in the below code might be correct but the variable whatever would have only one value that also only during the last count of the for each loop would exist
<script>
<c:forEach items="${detail}" var="u">
<c:set value="${u.content}" var="c"/>
var whatever = ${c};
</c:forEach>
<script>
for instance if the loop for the variable detail is of list type that consists of string type objects in it like "A" , "B" ,"C" then in the case the value of the var whatever will be "C", this is because jstl is compile time language.
So the above code won't work in for each loop
the following code might help you out or atleast provide you a idea for same.
<script>
var whatever = new Array;
<c:forEach items="${detail}" var="u">
<c:set value="${u.content}" var="c"/>
for (var i=0;i<whatever.length;i++)
{
whatever[i]=${c};
}
</c:forEach>
<script>

EL define array to output object properties

In PHP, I commonly would do something like this:
foreach(array('street','town','county','postcode') as $e) {
echo $address[$e] . '<br/>';
}
It's concise and easy to work with. Is there any way of doing this in EL? I'm having trouble finding a good way to do it cleanly.
There's nothing like that in standard JSTL/EL, but you could use JSTL fn:split() to split a single delimited string to an array:
<c:forEach items="${fn:split('street,town,county,postcode', ',')}" var="e">
${address[e]}<br/>
</c:forEach>
(provided that ${address} points to a Map with the given values as keys or a Javabean with the given properties)
Or if the ${address} is indeed a Map which contains only those keys already, you could also just loop over the Map itself:
<c:forEach items="${address}" var="entry">
${entry.value}<br/>
</c:forEach>
(the map key can in the above example be printed by ${entry.key}; also note that you need LinkedHashMap in order to maintain insertion order)
Typically you would populate a map or list server side, then output them on your JSP using JSTL for each loop something like below:
<c:forEach items="${formBean.myMap}" varStatus="itm">
<tr>
<td>${itm.key.propertyName}</td>
<td>${itm.value.propertyName}</td> <!--which is same as below ... -->
<td>${formBean.myMap[itm.key].propertyName}</td>
</tr>
</c:forEach>

Resources