3

The Thymeleaf documentation states about sorting lists:

/*
 * Sort a copy of the given list. The members of the list must implement
 * comparable or you must define a comparator.
 */
${#lists.sort(list)}
${#lists.sort(list, comparator)}

In my document model, I have a list of maps with key value pairs (the published_content list from the JBake static page generator). In my template, I want to sort this list by comparing the value stored under a certain key in the maps.

In other words, the list variable has type List<Map<String, Object>> and I want to sort this list by comparing the value in each map stored under the key "mykey".

How can I formulate such a comparator in the template?

Leandro Carracedo
  • 7,233
  • 2
  • 44
  • 50
haui
  • 567
  • 5
  • 18

2 Answers2

3

The question is more related to a pure Java sorting issue, as you need a way to sort a list of maps, this was already answered here.

Related code:

public Comparator<Map<String, String>> mapComparator = new Comparator<Map<String, String>>() {
    public int compare(Map<String, String> m1, Map<String, String> m2) {
        return m1.get("name").compareTo(m2.get("name"));
    }
}

Collections.sort(list, mapComparator);

After having your list sorted working, using mapComparator, you could use the Thymeleaf expression ${#lists.sort(list, comparator)} as explained in the docs.

Community
  • 1
  • 1
Leandro Carracedo
  • 7,233
  • 2
  • 44
  • 50
  • The problem is how to get this `mapComparator = new Comparator(...)` into the template? Where to define it and how to access this custom code from the templates...? – haui Jul 14 '15 at 06:21
  • 1
    You need to add the mapComparator as an attribute to the model in the controller: model.addAttribute("mapComparator",mapComparator); then in your template you could use: ${#lists.sort(yourlist, mapComparator)} – Leandro Carracedo Jul 14 '15 at 19:56
  • 1
    That's fine, if you have access to both, the templates **and** the code hosting the template engine. When using templates e.g. for generating static sites with JBake, this is not an option, because one has to also modify the page generator. When I were able to modify the model behind the templates, I could also add an object providing the whole sorting method. I thing, the existence of this `#lists.sort()` function makes less sense in this scenario. What I was looking for is a mechanism to define the comparison within the template itself. – haui Jul 15 '15 at 21:16
  • It may be an idea to look at using the Groovy template support instead for this type of thing... – jonbullock Sep 21 '15 at 16:09
1

In Thymeleaf you need to use the full classname (include package). Something like:

<span th:each="doc : ${#lists.sort(documents, new com.mycompany.myapp.comparator.DocumentNameComparator())}">
    ...
</span>
Michael Hegner
  • 5,555
  • 9
  • 38
  • 64