Spring MVC - Thymeleaf 表单与数组列表的绑定 [英] Spring MVC - Thymeleaf form binding with an arraylist

查看:65
本文介绍了Spring MVC - Thymeleaf 表单与数组列表的绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在特定视图中,我确实有一个可扩展的员工列表.每个员工有 2 个字段,它们是 hoursWorked &预付款.单击 1 个按钮,我想发布整个表单.为了实现这一点,我向包含多个 POJO(基于员工人数)的视图发送了一个列表.

添加到列表中的 POJO 如下所示:

@Setter@Getter@NoArgsConstructor公共类 WorkdayCommand {私人长雇员ID;私人整数小时工作;私人整数预付款;}

在控制器中,我确实有一行将列表添加到模型中:

model.addAttribute("workdayCommands", employeeService.getListOfWorkdayCommandsWithIds());

以及形成实际列表的方法:

public ListgetListOfWorkdayCommandsWithIds(){列表<WorkdayCommand>listOfCommands = new ArrayList<>();列表<长>listOfIds = employeeRepository.getListOfIds();for(int i = 0; i 

现在,我的观点有问题:

<div class="table-responsive" th:if="${not #lists.isEmpty(employees)}"><form th:object="${workdayCommands}" th:action="@{/addworkday}">一些表头...<tr th:each="employee : ${employees}"><td><a href="#" role="button" th:href="@{'/employee/' + ${employee.id}}" th:text="${employee.name}">迈克·科瓦尔斯基</a></td><td><input type="text" class="form-control" placeholder="Enter hours" th:field="*{hoursWorked}"></td><td><input type="text" class="form-control" placeholder="输入付款" th:field="*{advancePayment}"></td><td><input type="hidden" th:field="*{id}"/></td></tr></表单>

到目前为止,我一直收到一个错误:

NotReadablePropertyException:bean 类 [java.util.ArrayList] 的无效属性hoursWorked":Bean 属性hoursWorked"不可读或具有无效的 getter 方法

如何正确绑定数组列表和视图?我想问题是数组列表中没有 hoursWorked 这样的字段.我应该使用什么 th:field 参数来获取实际的 WorkdayCommand.hoursWorked 字段,然后遍历列表以获取所有员工?如果您需要更多信息,请随时询问.

我正在尝试以下方法:

th:field="*{[__${iter.index}__].hoursWorked}"

...但这仍然不起作用.我无法与列表中的第一个 POJO 联系起来.

编辑 2

我的完整视图如下所示:

在单个表格行中,我确实有一些员工信息以及 2 个输入和 2 个按钮.每一行的创建归功于:

 

当点击提交按钮时,会创建一个新的 Workday 对象,然后将其保存到数据库中.发生这种情况时,Workday 需要与相应的员工相关联.所以我的:

 

...我还分配了一个隐藏的 id 字段.然后我们有 WorkdayCommand 从视图中收集所有信息.所以 employeeId 字段是我将工作日与相应员工相关联的方式.它应该使用为每个显示所有信息传递的 id 值.希望现在清楚了.

解决方案

您不能直接绑定到 ArrayList 作为 th:object.相反,您应该创建一个将 ArrayList 作为属性的对象.

@Setter@Getter@NoArgsConstructor公共类 WorkdayForm {私人列表<WorkdayCommand>workdayCommands = new ArrayList<>();}

然后循环遍历,并像这样绑定它们:

<!-- 表头--><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="输入付款" th:field="*{workdayCommands[__${i.index}__].advancePayment}"><<;/td><td><input type="hidden" th:field="*{workdayCommands[__${i.index}__].employeeId}"/></td></tr><!-- 表页脚--></表单>

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

My full view looks like this:

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.

解决方案

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>

这篇关于Spring MVC - Thymeleaf 表单与数组列表的绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆