Reputation: 1224
On a specific view I do have an expandable list of employees. Each employee has 2 fields and those are hoursWorked
& advancePayments
. With 1 button click, I would like to post the whole form. To achieve this, I'm sending a list to the view that contains several POJOs (based on number of employees).
A POJOs that are added to the list look like this:
@Setter
@Getter
@NoArgsConstructor
public class WorkdayCommand {
private Long employeeId;
private Integer hoursWorked;
private Integer advancePayment;
}
In a controller, I do have a line to add the list to the model:
model.addAttribute("workdayCommands", employeeService.getListOfWorkdayCommandsWithIds());
And the method forming the actual list:
public List<WorkdayCommand> getListOfWorkdayCommandsWithIds(){
List<WorkdayCommand> listOfCommands = new ArrayList<>();
List<Long> listOfIds = employeeRepository.getListOfIds();
for(int i = 0; i < employeeRepository.getNumberOfEmployees(); i++){
WorkdayCommand workdayCommand = new WorkdayCommand();
workdayCommand.setEmployeeId(listOfIds.get(i));
listOfCommands.add(workdayCommand);
}
return listOfCommands;
}
Now, I am having a problem with my view:
<div class="table-responsive" th:if="${not #lists.isEmpty(employees)}">
<form th:object="${workdayCommands}" th:action="@{/addworkday}">
some table headers...
<tr th:each="employee : ${employees}">
<td><a href="#" role="button" th:href="@{'/employee/' + ${employee.id}}" th:text="${employee.name}">Mike Kowalsky</a></td>
<td><input type="text" class="form-control" placeholder="Enter hours" th:field="*{hoursWorked}"></td>
<td><input type="text" class="form-control" placeholder="Enter payment" th:field="*{advancePayment}"></td>
<td><input type="hidden" th:field="*{id}"/></td>
</tr>
</form>
</div>
So far, I keep getting an error:
NotReadablePropertyException: Invalid property 'hoursWorked' of bean class [java.util.ArrayList]: Bean property 'hoursWorked' is not readable or has an invalid getter method
How to properly bind the arraylist with the view? I guess the problem is that there's no such field in the arraylist as hoursWorked
. What th:field
parameter should I use, to get to the actual WorkdayCommand.hoursWorked
field and then iterate through the list to get through all the employees? If you need any more information, feel free to ask any time.
I'm trying with things like:
th:field="*{[__${iter.index}__].hoursWorked}"
...but that still doesn't work. I can't relate to the first POJO on the list.
edit 2
In a single table row I do have some employee information as well as 2 inputs and 2 buttons. Each row is created thanks to:
<tr th:each="employee : ${employees}">
When a submit button is hit, a new Workday object is created and then persisted to the database. When this happens, a Workday needs to be associated to a corresponding employee. So with my:
<tr th:each="employee : ${employees}">
...I'm also assigning a hidden id
field. Then we have the WorkdayCommand
that gathers all the information from the view. So the employeeId
field is my way of associating a Workday to a corresponding employee. It should use the id
value that was passed by for each that displayed all the information. Hope it's clear now.
Upvotes: 3
Views: 2616
Reputation: 20477
You can't bind directly to an ArrayList
aS the th:object
. Instead you should create an object that has the ArrayList as a property.
@Setter
@Getter
@NoArgsConstructor
public class WorkdayForm {
private List<WorkdayCommand> workdayCommands = new ArrayList<>();
}
Then you loop through, and bind them like this:
<form th:object="${workdayForm}" th:action="@{/addworkday}">
<!-- table headers -->
<tr th:each="workdayCommand, i : ${workdayForm.workdayCommand}">
<td><input type="text" class="form-control" placeholder="Enter hours" th:field="*{workdayCommands[__${i.index}__].hoursWorked}"></td>
<td><input type="text" class="form-control" placeholder="Enter payment" th:field="*{workdayCommands[__${i.index}__].advancePayment}"></td>
<td><input type="hidden" th:field="*{workdayCommands[__${i.index}__].employeeId}"/></td>
</tr>
<!-- table footers -->
</form>
Upvotes: 5