С определенной точки зрения у меня есть расширяемый список сотрудников. У каждого сотрудника есть 2 поля, это hoursWorked и advancePayments. Одним нажатием кнопки я хочу опубликовать всю форму. Для этого я отправляю в представление список, содержащий несколько POJO (в зависимости от количества сотрудников).
POJO, добавленные в список, выглядят следующим образом:
@Setter
@Getter
@NoArgsConstructor
public class WorkdayCommand {
private Long employeeId;
private Integer hoursWorked;
private Integer advancePayment;
}
В контроллере у меня есть строка для добавления списка к модели:
model.addAttribute("workdayCommands", employeeService.getListOfWorkdayCommandsWithIds());
И способ формирования фактического списка:
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;
}
Теперь у меня проблема с моим представлением:
<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>
Пока продолжаю получать ошибку:
NotReadablePropertyException: Invalid property 'hoursWorked' of bean class [java.util.ArrayList]: Bean property 'hoursWorked' is not readable or has an invalid getter method
Как правильно привязать аррайлист к просмотру? Думаю, проблема в том, что в Arraylist нет такого поля, как hoursWorked. Какой параметр th:field мне следует использовать, чтобы перейти к фактическому полю WorkdayCommand.hoursWorked, а затем перебрать список, чтобы пройти через всех сотрудников? Если вам нужна дополнительная информация, не стесняйтесь спрашивать в любое время.
Я пытаюсь с такими вещами:
th:field = "*{[__${iter.index}__].hoursWorked}"
... но это все равно не работает. Я не могу относиться к первому POJO в списке.
редактировать 2
В одной строке таблицы у меня есть информация о сотрудниках, а также 2 ввода и 2 кнопки. Каждая строка создается благодаря:
<tr th:each = "employee : ${employees}">
При нажатии кнопки отправки создается новый объект Workday, который затем сохраняется в базе данных. Когда это происходит, рабочий день необходимо связать с соответствующим сотрудником. Итак, с моим:
<tr th:each = "employee : ${employees}">
... Еще я назначаю скрытое поле id. Затем у нас есть WorkdayCommand, который собирает всю информацию из представления. Таким образом, поле employeeId - это мой способ связать рабочий день с соответствующим сотрудником. Он должен использовать значение id, которое было передано для каждого, который отображал всю информацию. Надеюсь, теперь все ясно.
Есть какие-нибудь указания о том, где мне это делать? В теге form?




Вы не можете напрямую привязать ArrayList как th:object. Вместо этого вы должны создать объект, имеющий в качестве свойства ArrayList.
@Setter
@Getter
@NoArgsConstructor
public class WorkdayForm {
private List<WorkdayCommand> workdayCommands = new ArrayList<>();
}
Затем вы выполняете цикл и связываете их следующим образом:
<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>
Хорошо. Это разумно. Есть еще одна проблема. Во-первых, при переборе сотрудников скрытому полю id присваивается значение. То же значение необходимо передать в поле employeeId в объекте поддержки. Таким образом, я буду уверен, что часы и оплата будут назначены правильному сотруднику. Я не могу включить 2 th:each в одну строку таблицы ... Есть какие-нибудь подсказки, как решить эту проблему?
Я не совсем понимаю, что вы имеете в виду ... что такое employeeId на workCommand? Зачем нужно перебивать сотрудников?
workdayCommand должен иметь сотрудника в качестве своего свойства, тогда ... в рамках цикла вы можете отображать информацию о сотруднике следующим образом: <td><a href = "#" role = "button" th:href = "@{'/employee/' + ${employee.id}}" th:text = "${workdayCommand.employee.name}">Mike Kowalsky</a></td>
В качестве альтернативы вы можете просто перебрать employee вместо workdayCommand. Насколько я понимаю, все останется по-прежнему.
Вам также следует выполнить итерацию на
workdayCommands, как и наemployees.