Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continuous numeration of nested loop items in Thymeleaf

Tags:

java

thymeleaf

I am writing a template which should render list of employees. Employees are passed to Thymeleaf in form of list of departments where each department has its own list of employees.

As my task is to display them all - the problem is to handle continous numeration. Each employee should appear as a row with next number.

Following attempt allows to index employees of given department, with new numeration per department:

<table th:each="department, depStatus : departmentList">
    <tr th:each="employee, empStatus : department.employees">
        <td th:inline="text">[[${empStatus.index+1}]]</td>

But my point is to keep continuous numeration through all departments, just like this:

1. Employee A from Dept X
2. Employee B from Dept X
3. Employee C from Dept Y

I know I can make this structure flat at server side, but I cannot believe that it is the only way.

I have also tried to intruduce local variable with th:with="idx = 0" and then increment it somewhere with th:with="idx = ${idx} + 1, but this simply overrides outter idx value.

like image 324
Maciej Dobrowolski Avatar asked Jan 30 '15 13:01

Maciej Dobrowolski


Video Answer


2 Answers

What you trying to achieve is to update a local variable and have the new value be visible in a scope wider than where the update was made. That's why it contradicts with th:with definition. I think you can't avoid making some server side tweaking for example providing some flatter view of your structure as you suggested.

On the other side, a quick solution, (assuming you are not strictly towards using a table) it might be trying an ordered list while using th:blocks for the enclosing department :

<ol>
  <!--/*/ <th:block th:each="dept : ${departmentList} "> /*/-->

   <li th:each="emp : dept.employees" th:text="|${emp.name} from ${dept.name}|"></li>

  <!--/*/ </th:block> /*/-->
</ol>  
like image 102
gregdim Avatar answered Oct 19 '22 22:10

gregdim


Let's see if I understand your problem:

You have a model where employees are assigned to departments. According to your description of the problem, a department object has a list of employees assigned to it.

From what I saw, you are taking from your controller class to your vision a collection of departments.

The Thymeleaf enables the use of iteration in elements through th:each attribute, as you already know. You can slightly reduce your code performing an iteration only in the collection of employees, such as:

<table>
    <tr th:each="employee, empStatus : ${department.employees}">

NOTE: If I'm not mistaken, the result of your template will repeat the table element due to the number of departments.

That way, your code will be cleaner, and you can just focus on working with employees.


In relation to the main question on the definition of an index for each line, you can use something known as "iteration status".

I believe you already know something about it, but I'll try to explain my way, which might enlighten you something:

According to the Thymeleaf documentation, you can use a variable provided by Thymeleaf that will give you access to some information about the iteration being made. With this variable, you can gather some information with properties of which are cited in the Thymeleaf documentation (check session 6.2):

The current iteration index, starting with 0. This is the index property. The current iteration index, starting with 1. This is the count property. The total amount of elements in the iterated variable. This is the size property. The iter variable for each iteration. This is the current property. Whether the current iteration is even or odd. These are the even/odd boolean properties . Whether the current iteration is the first one. This is the first boolean property. Whether the current iteration is the last one. This is the last boolean property.

To access this variable, you need to declare it soon after the declaration of the item that represent each iteration made, as you did previously:

<tr th:each="employee, empStatus : ${department.employees}">

You can also omit the declaration of this variable and still use it. This is only possible because the Thymeleaf make this statement to you, where it takes the name given to variable representing each iteration element (in this case "employee"), and add the suffix "Stat" to it (resulting on "employeeStat").

You will have access to this variable and its internal properties only within the code fragment defined by the tag with th:each attribute.

If you know how to display rows and columns in your web application page, all you have to do is use the properties of the iteration status variable, such as:

<td th:text="${empStatus.index}"></td>

Or, if you prefer:

<td th:text="${empStatus.count}"></td>

If you have any questions, please comment and I will edit my answer to a better understanding.


EDIT

Oh, I understand only now what's your real problem, sorry.

If you want to create a list where the name of each employee to appear followed by the name of their respective department, and each list item with a different number (all ordained), then the problem is quite simple.

All you have to do at first is to go through all departments, displaying the name of the employee followed by the name of the department, as you wish. This will solve part of the problem, as this is just a simple matter of logic and use of iteration.

To make that happen regularly ordained, that is, with each record / item listed in order, you can, for example, create a local variable, one of the other resources in Thymeleaf.

To quickly learn about setting and use this type of resource, check this link: setting up a value for a variable name in thymeleaf

Or you can check the documentation of Thymeleaf (Session 9): http://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#local-variables

After creating your variable, try to use it as a counter, where it will be incremented for each record listed.

I hope this is helpful and solve your problem. If that does not work, please comment again and I will try another solution. Likewise, if this is not really your question, please comment also.

NOTE: Again I ask you to be careful in your loop structure. You may be creating a repeating structure that create multiple table structures in HTML code, which I believe not be what you want. Also, make sure to check if you are performing arithmetic operations correctly. I believe that your increment operation must be within the braces {}, and not out of them.


EDIT 2

I searched all over the place in order to do this ... But unfortunately I could only find this:

Counters in Loops in Thymeleaf

You can find more about this in the Thymeleaf documentation (Appendix B - Numbers). This is a valid way to do a loop with Thymeleaf. However, it is difficult to make a nested loop because we work in Thymeleaf with attributes, and not with tags / HTML elements. In case, you would create a new line only within a nested loop, something that is not possible. Maybe you can try to use the "th:each" attribute twice, in the same "tr" tag, such as:

<tr th:each="" th:each"">
</tr>

Although I believe this will not work too...

I really apologize, Maciej, as this is not a final answer, and so, not really helpfull. However, I ask you to stop just a minute and try to review your web application. Just think, you are wanting to design a table, ordering things, listing all with numbers. Would it not be better to do this in Java code? Moreover, would not you try to do this in SQL? Would not you rather get sorted results of a database with SQL? Realize that you are making an organization work here, where each employee in each department would be listed, with departments as order.

You see, I'm not saying that you are doing it wrong, but under the circumstances, and if we stop to analyze, we developers usually get ordered results from the business layer of an application, and we let the view layer responsible for only display them.

If this is not possible in your application, and the link that I sent you now can not direct you to solve your problem, then I'm terribly sorry, but I can not do anything else. Maybe it's time to you ask this in Thymeleaf forum where its developers may probably help you (probably):

http://forum.thymeleaf.org/General-Usage-f2234430.html

I sincerely hope you can succeed in your problem, solving it. And if you do, please, I kindly ask you to share your solution with everyone here, since many people may one day end up facing the same situation.

Até depois, e boa sorte amigo.

like image 29
Loa Avatar answered Oct 19 '22 22:10

Loa