Spring MVC - связывание формы Thymeleaf с arraylist

С определенной точки зрения у меня есть расширяемый список сотрудников. У каждого сотрудника есть 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

Мой полный вид выглядит так: Spring MVC - связывание формы Thymeleaf с arraylist

В одной строке таблицы у меня есть информация о сотрудниках, а также 2 ввода и 2 кнопки. Каждая строка создается благодаря:

 <tr th:each = "employee : ${employees}">

При нажатии кнопки отправки создается новый объект Workday, который затем сохраняется в базе данных. Когда это происходит, рабочий день необходимо связать с соответствующим сотрудником. Итак, с моим:

 <tr th:each = "employee : ${employees}">

... Еще я назначаю скрытое поле id. Затем у нас есть WorkdayCommand, который собирает всю информацию из представления. Таким образом, поле employeeId - это мой способ связать рабочий день с соответствующим сотрудником. Он должен использовать значение id, которое было передано для каждого, который отображал всю информацию. Надеюсь, теперь все ясно.

Вам также следует выполнить итерацию на workdayCommands, как и на employees.

xingbin 13.03.2018 15:20

Есть какие-нибудь указания о том, где мне это делать? В теге form?

Maciaz 13.03.2018 15:26
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
2
1 507
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы не можете напрямую привязать 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 в одну строку таблицы ... Есть какие-нибудь подсказки, как решить эту проблему?

Maciaz 13.03.2018 15:55

Я не совсем понимаю, что вы имеете в виду ... что такое employeeId на workCommand? Зачем нужно перебивать сотрудников?

Metroids 13.03.2018 16:00

workdayCommand должен иметь сотрудника в качестве своего свойства, тогда ... в рамках цикла вы можете отображать информацию о сотруднике следующим образом: <td><a href = "#" role = "button" th:href = "@{'/employee/' + ${employee.id}}" th:text = "${workdayCommand.employee.name}">Mike Kowalsky</a></td>

Metroids 13.03.2018 17:59

В качестве альтернативы вы можете просто перебрать employee вместо workdayCommand. Насколько я понимаю, все останется по-прежнему.

Metroids 13.03.2018 18:00

Другие вопросы по теме