Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thymeleaf #lists.contains() expression utility not working

I'm working with the thymeleaf standard dialect and trying to render a list of checkboxes in a form. The rendering is ok, however, the problem is where I try to apply the "checked" property to the checkboxes using the thymeleaf #lists.contains() expression utility method.

So I have a model class that has the following fields:

private List<Template> templates;

@FormParam("selectedTemplates")
private List<String> selectedTemplates = Lists.newArrayList();

A Thymeleaf template html fragment:

<div th:each="template : *{templates}">
    <input type="checkbox" name="selectedTemplates" th:value="${template.id}" 
    th:checked="${#lists.contains(product.selectedTemplates, template.id)}" />
    <label th:text="${template.filename} + ' (' + ${template.description} + ')'" />
    <!-- Attempt to use the list contains to check the field -->
    <div th:text="${product.selectedTemplates}"/>
    <div th:text="${template.id}"/>  
    <div th:text="${#lists.contains(product.selectedTemplates, template.id)}" />
</div>

The output on the page for one of the checkboxes that should be selected.

<input type="checkbox" name="selectedTemplates" value="4" /> (Template Name)
<div>[4,5]</div>
<div>4</div>
<div>false<div>

So as you can see, I print the list which has values [4,5] and I use the #lists.contains method to see if it has template.id in it, however, the method always returns false. I even tried some hard coded ids to test the method and I always get "false" back.

For example:

<div th:text="${product.selectedTemplates}"/>
<div th:text="${#lists.contains(product.selectedTemplates, 4)}" />

Prints [4,5]false

<div th:text="${product.selectedTemplates}"/>
<div th:text="${#lists.contains(product.selectedTemplates, '4')}" />

Prints [4,5]false

Not sure what I'm doing wrong, but it seems so straight forward, not sure what else to try. My guess is there is something wrong with the syntax. Any suggestions or advice is greatly appreciated. I'm not able to find any resources on troubleshooting this problem, the thymeleaf guide quickly glosses over that section.

like image 588
Tom Lerma Avatar asked Dec 18 '13 19:12

Tom Lerma


2 Answers

i know the question is old, but i post this answer so can be useful to others users having the same problem.

i don't know if it's you or another user, but here i found that we must add

'' + template.id

so:

th:checked="${#lists.contains(product.selectedTemplates, '' + template.id)}" 

for me it worked! Thank you

like image 66
SaganTheBest Avatar answered Oct 09 '22 09:10

SaganTheBest


I did some further experimentation and found an issue where the #lists.contains() utility method does not work for a single character string. I would add that I'm using thymeleaf 2.0.19, but also tried 2.1.1.RELEASE with the same result.

I created a simple list in my model and added some values:

@FormParam("testList") 
private List<String> testList = Lists.newArrayList(); 

testList.add("test1"); 
testList.add("test2"); 
testList.add("3"); 
testList.add("P"); 
testList.add("33");

Then tested the #lists.contains() method like so:

<div th:text="${product.testList}"/>
<div th:text="${#lists.contains(product.testList, 'test1')}"/>
<div th:text="${#lists.contains(product.testList, 'test2')}"/>
<div th:text="${#lists.contains(product.testList, '3')}"/>
<div th:text="${#lists.contains(product.testList, 'P')}"/>
<div th:text="${#lists.contains(product.testList, '33')}"/>

And the output is as follows:

<div>[test1, test2, 3, P, 33]</div>
<div>true</div>
<div>true</div>
<div>false</div>
<div>false</div>
<div>true</div>

So, clearly the method does not work for single character strings. Because I'm working on a new project I simply reset the sequences driving these ids so that I don't have any single character id's to work with. That is certainly not the solution I was hoping for but it works. I will also add that in order to get the method to work in the context of my question, I had to add an empty character to my id like so:

th:checked="${#lists.contains(product.selectedTemplates, '' + template.id)}"

Without it, the contains method would return "false" because template.id is a Long type.

like image 44
Tom Lerma Avatar answered Oct 09 '22 08:10

Tom Lerma