EL define array to output object properties - spring

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>

Related

pass thymeleaf variable as parameter in method

I concatenate the state and my stateCounter to one String. This is my value for my HashMap which stores all the States but I don't get it to to put this variable in my method.
<span th:with="stateName=${item.state} + ${item.stateCounter}"></span>
<td th:text="${{order.getStateRepository().get(${stateName})}}"></td>
Some notes:
(1) Using a <td> tag suggests you are also using a <table>. Having a <span> tag next to a <td> tag inside a table is not valid HTML (assuming this is what it looks like in your template - maybe this is just a copy/paste thing).
(2) If your order object has a stateRepository field, then you don't need to use a getter order.getStateRepository(). You can just use the field name order.stateRepository. You are already doing this with item.state, for example. Thymeleaf will figure out from the field name how to use the related getter - e.g. item.getState().
(3) The scope (availability/visibility) of a local variable, such as stateName in th:with="stateName=${item.state} is limited to the tag in which it is declared, and also to any sub-tags. You do not have any sub-tags in your <span> - therefore the variable is not visible anywhere outside of your span. So, it is not available inside the <td> tag.
(4) Do you need to use a local variable in your example?
Instead of using get(stateName), you can use the expression referred to by stateName directly:
get(item.state + item.stateCounter)
So overall, this should work (based on the assumptions above):
<td th:text="${order.stateRepository.get(item.state + item.stateCounter)}"></td>
Maybe you do need the local variable, of course. It may depend on the wider context of the Thymeleaf template.
You are trying to use local variable. It will work if you try as follows:
<div th:with="stateName=${item.state} + ${item.stateCounter}">
<td th:text="${order.getStateRepository().get(stateName)}"></td>
</div>

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.

Complicated xpath for a rookie

I have this piece of html:
<tr>
<td class="has-checkbox">
<input id="abc" class=... value=...>
</td>
<td class="has-label">
<label for="abc">Name1234</label>
</td>
<tr>
I need to make an xpath that gets me the input element, based on whats in the label, in this case Name1234.
In other words, for this case, I need an xpath to the input element, and the path must contain Name1234, as its variable.
Anyone who can help me out here?
//input[#id = //label[. = 'Name1234']/#for] selects input element(s) with an id attribute value equal to the for attribute value of label elements where the contents is Name1234.
You can use /.. , this syntax use to move back to parent node. In your case:
//label[.='Name1234']/../../td/input
You must move back 2 times because input tag is the child of another td tag.
Here are others introduction and example about you should read.
Here is a solution using the Axes parent and preceding-sibling:
//label[.='Name1234']/parent::td/preceding-sibling::td/input
It's not so complicated as you think:
xpath=//tr[//label[.="Name1234"]]//input
in other words, you are looking for the 'tr' which contains 'label' with text "Name1234". If the condition is true, you are getting the 'input' element

iterating of muliple items in 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>

JSTL: I need to access hashtable using a key

I know this works: <c:out value="${model.testhash['A']}"/>
but I need something like:
<c:out value="${model.testhash[${model.testkey}]}"/>
Is this possible?
Have you tried
${model.testhash[model.testkey]}
In general the ${ } only delineates the JSTL expression, you don't need to escape the lookup for the model.testkey lookup as well, so it is also possible to do:
${model.testhash[model.condition ? 'A' : 'B']}
.. just as an example.

Resources