Thymeleaf Iteration: Use index as ArrayIndex inside th:each loop - java

I want to use the index of an thymeleaf-loop as arrayindex inside.
Example:
<div th:each="service : ${requestedServices}">
<div class="col-sm-1">
<input type="checkbox" th:checked=*{service[index of loop?].requested}">
</div>
</div>
I'll already tried to use serviceStat.index inside the array
${requestedServices} is an ArrayList of Requested Service
class RequestedService {
Service service
boolean requested
}
class Service {
String name;
int value;
}
I hope to find an answer for my problem

serviceStat.index is the correct way to to index into your array (see the last paragraph of keeping iteration status -- If you don’t explicitly set a status variable, Thymeleaf will always create one for you by suffixing Stat to the name of the iteration variable:).
That being said, because you are using it in a th:field attribute, you must use preprocessing for your index.
<div th:each="service : ${requestedServices}">
<div class="col-sm-1">
<input type="checkbox" th:checked="*{service[__${serviceStat.index}_].requested}" />
</div>
</div>
(You might also be interested in the Thymeleaf tutorial on dynamic fields.)

Related

How to generate edit modals for each element in the model?

I'm trying to use thymeleaf to generate edit and delete modals for each element in the model in my ModelAndView using th:each.
The modals are indeed created and have unique ids based on the id field of the elements. The problem I have is none of the values from elements are parsed into the inputs to enable the user to see the current values.
They are obviously there because the view also has a table which displays each element's values along with the anchors which toggle the modals.
Here's some example code of how I'm doing it:
<div th:each="f : ${foos}" th:id="um- + ${f.id}" class="modal fade"
tabindex="-1" role="dialog">
...
<form role="form" th:action="#{/foo/update}" th:object="${foo}" th:method="post">
<input type="hidden" th:field="*{id}" th:value="${f.id}"/>
<fieldset class="form-group">
<label for="bar">Bar</label>
<input th:field="*{bar}" th:value="${f.bar}" class="form-control"
id="bar" type="text" placeholder="Bar"/>
</fieldset>
...
</form>
...
</div>
How to generate edit modals for each element in the model? I'm not sure why thymeleaf is unable to get the values of the fields from the model elements.
That's not a great approach actually. In addition to it not working, doing using a loop obviously creates n modals for the collection.
The solution that worked best was to provide a single modal that would be populated and submitted with Ajax calls.
This no-frills Spring Boot app has all the relavant code.

can't reference iteration variable in Thymeleaf

I try to iterate a list of items using th:each,
<div class="row" th:each="item : *{items}">
<input type="text" th:field="item.name"/>
</div>
it works if I access the iteration variable using th:text, but throws
java.lang.IllegalStateException: Neither BindingResult nor plain
target object for bean name 'item' available as request attribute
when I use th:field to access it, where did I do wrong?
Something like this could work:
<div class="row" th:each="item, stat : *{items}">
<input type="text" th:field="*{items[__${stat.index}__].name}"/>
</div>
Take a peek here for more info: http://forum.thymeleaf.org/I-have-problem-in-binding-the-list-of-objects-contained-inside-a-object-on-the-form-using-thymeleaf-td3525038.html
th:field is broken in several ways, this is one of them.

value input field in foreach to input field outside foreach

The problem I have is best explained with a code example:
I have the following VIEW.jsp:
<c:forEach var="widget" items="${widgets}">
<div class="drag">
<p>Id: ${widget.id}</p>
<input class="editWidget" type="image" src="/tis/img/icons/edit.png" alt="Edit widget">
<input class="idWidget" type="hidden" value="${widget.id}">
</div>
</c:forEach>
<div id="editDialog" title="Edit widget">
<fieldset>
<input class="editWidgetId" type="hidden" value="??" id="editWidgetId">
</fieldset>
</div>
editWidgetId should have its 'value' attribute filled with the value of idWidget inside the foreach loop. This value should be different for each element in the loop (element is selected by edit button).
The questions:
How can I get the value of one input field to another input field?
How can I do this when a foreach loop is present?
Thanks in advance
Given you want dynamic behavior, this work has to be executed on the client-side by JavaScript as at the server-side, you have many widgets to one editDialog and are lacking the client-side user event to make your decision.
What you want to do is assign a function handler (or statement in my example below) to each editWidget to change the value of the editWidgetId input box with the appropriate value:
<input onclick="document.getElementById('editWidgetId').value = '${widget.id}'" class="editWidget" type="image" src="/tis/img/icons/edit.png" alt="Edit widget" >
Haven't tested this but I hope you get the idea

Inconsistent Expression Language behaviour, same expression different values

The same EL expression ${taskId} gives two different values in different places.
I am using the Stripes framework, along with MongoDB and Morphia for Object-Mapping (and of course Java/JSP/etc).
Using the following JSP/Expression Language code:
<c:forEach items="${actionBean.tasks}" var="listTask">
<c:set var="taskId" scope="page" value="${listTask.id}"/>
<s:form method="post" beanclass="action.TaskActionBean">
${taskId}<s:hidden name="task.id" value="${taskId}"/>
<s:submit name="promoteTask" value="Up" />
</s:form>
</c:forEach>
Gives the following generated code:
<form method="post" action="/scrumyogi/">
4ef99b730364de7ec70dbd68
<input type="hidden" value="4ef99b6c0364de7ec70dbd67" name="task.id">
<input type="submit" value="Up" name="promoteTask">
<div style="display: none;">
<input type="hidden" value="NPNEJw6tUWfRBXf-vVOLTw==" name="_sourcePage">
<input type="hidden" value="XbfUDiSHGrU=" name="__fp">
</div>
</form>
As you can see ${taskId} is printing out 4ef99b730364de7ec70dbd68 and then 4ef99b6c0364de7ec70dbd67, which makes no sense to me, I need ${taskId} to print out the same value 4ef99b730364de7ec70dbd68 is the correct one.
Is there some known issue that could cause this.
EDIT: the real problem is that the ${taskId} within the hidden form tag is incorrect, I printed the other value to see what the expression contains, and then found that it's different in the different locations - which make things seriously confusing.
ActionBean code:
#UrlBinding("/")
public class TaskActionBean extends BaseActionBean{
String taskId;
Task task = new Task();
List<Task> tasks;
public final static String DISPLAY = "/index.jsp";
#DefaultHandler
public Resolution listTasks(){
tasks = Dao.datastore().find(Task.class).order("rank").asList();
return new ForwardResolution(DISPLAY);
}
public Resolution promoteTask(){
task.promoteTask();
tasks = Dao.datastore().find(Task.class).order("rank").asList();
return new ForwardResolution(DISPLAY);
}
// ... getters and setters
You have a taskId field in you action bean, and according to stripes taglib documentation:
The hidden tag assigns the value attribute by scanning in the following order:
for one or more values with the same name in the HttpServletRequest
for a field on the ActionBean with the same name (if a bean instance is present)
by collapsing the body content to a String, if a body is present
referring to the result of the EL expression contained in the value attribute of the tag.
So it probably finds the field in your action bean and takes the value from there.
The other (jsp el) ${taskId} is assigned from task list element.
Change the taskId to some name that doesn't coincide with your action bean field and it should work.

Use object's method in a jstl page

I have a model with this method:
public List<String> getPriviledgeNames()
I'm trying to display a list of checkbox in my jstl page, and I'd like to checked only the ones which their name is in the list returned from my model.
So I have something like:
<li>
<input type="checkbox" name ="priviledge" id="CheckBox2" class="checkbox" value="clickthrough" />
<label for="CheckBox2">Clickthrough</label>
</li>
<li>
<input type="checkbox" name ="priviledge" id="CheckBox3" class="checkbox" value="details" />
<label for="CheckBox3">Details</label>
</li>
I'd like to add the checked="checked" only their name is in the list provided by my model's method. Is there a way to do this WITHOUT using scriptlet? I'd like to have no java code inside my pages...
Thanks for any helps!
Roberto
<c:when test = "${fn:contains(list,value)}">
-according to the docs it's actually doing a string/string comparison, so I assume it's actually checking whether the string value is a substring of list.toString().
You could also do a manual test on each value in the list with a forEach tag but that would be messier.
By using a map instead of a list could do something like this:
<c:if test="${yourModel.priviledgeNames['clickthrough'] ne null}">
checked="checked"</c:if>
Or just this: ${yourModel.priviledgeNames['clickthrough']} by mapping your checkbox name to checked="checked"

Categories