输入数组Thymeleaf

时间:2016-07-28 13:15:13

标签: java html arrays spring thymeleaf

我需要从一个数组中选择值并将其分配给其他数组。使用Spring Thymeleaf。不知道如何检索这些选择的值。 我的课程:

@Entity
public class Collaborator {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;

   @NotNull
   @Size (min=3, max=32)
   private String name;

   @NotNull
   @ManyToOne (cascade = CascadeType.ALL)
   private Role role;

   public Collaborator() {}...

@Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull
    @Size(min = 3, max = 99)
    private String name;

    public Role() {}....

我的控制器:

@RequestMapping("/project_collaborators/{projectId}")
public String projectCollaborators(@PathVariable Long projectId, Model model) {
    Project project = mProjectService.findById(projectId);
    List<Collaborator> allCollaborators = mCollaboratorService.findAll();
    List<Collaborator> assignments = new ArrayList<>();

    if (project.getRolesNeeded()!=null) {
        for (int i=0;i<project.getRolesNeeded().size();i++) {
            assignments.add(new Collaborator("Unassigned", project.getRolesNeeded().get(i)));
            assignments.get(i).setId((long) 0);
        }
    }

    model.addAttribute("assignments", assignments);
    model.addAttribute("allCollaborators", allCollaborators);
    model.addAttribute("project", project);

    return "project_collaborators";
}

@RequestMapping(value = "/project_collaborators/{projectId}", method = RequestMethod.POST)
public String projectCollaboratorsPost(@ModelAttribute Project project, @PathVariable Long projectId, Model model) {
    Project p = mProjectService.findById(projectId);


    //mProjectService.save(project);
    return "redirect:/project_detail/{projectId}";
}

模板:

            <form th:action="@{'/project_collaborators/' + ${project.id}}" method="post" th:object="${project}">
                <label th:text="'Edit Collaborators: ' + ${project.name}">Edit Collaborators: Website Project</label>
                <ul class="checkbox-list">

                    <li th:each="a : ${assignments}">
                        <span th:text="${a.role.name}" class="primary">Developer</span>
                        <div class="custom-select">
                            <span class="dropdown-arrow"></span>
                            <select th:field="${a.id}">
                                <option th:each="collaborator : ${allCollaborators}" th:value="${collaborator.id}" th:text="${collaborator.name}">Michael Pemulis</option>
                            </select>
                        </div>
                    </li>

                </ul>
                <div class="actions">
                    <input type="submit" value="Save" class="button"/>
                    <a href="#" class="button button-secondary">Cancel</a>
                </div>
            </form>

正如您所看到的,我想让用户从(allCollaborators)中为每个角色(roleNeeded)选择任何协作者,并将其分配到List(赋值)中。

我收到错误消息:

  

ava.lang.IllegalStateException:既不是BindingResult也不是普通目标   bean名称'a'的对象可用作请求属性

所以问题是:如何解决它,在模板中将值从一个数组赋值给另一个数组,并在我的控制器中检索这些值。

1 个答案:

答案 0 :(得分:1)

异常原因

你得到的 IllegalStateException 是因为你的 select 元素中的 th:field =“$ {a.id}”必须是相关的形式 th:object =“$ {project}”元素; th:field 属性必须引用项目实例中的实际字段(您还需要编写 th:field =“* {fieldName}”)。这应该可以解决您遇到的异常,但不会解决您的整个问题,因为它的第二部分与如何使值进入您的控制器有关,我将在下面解释。

将值发送到您的控制器

要将值输入控制器,您需要进行一些更改。由于我不太了解 Project 类的代码,因此我将更改一些内容,以便您能够弄清楚如何根据您的特定情况调整此简单示例。

首先,我了解您希望在表单中建立如下关系:

  • Role1 =&gt; CollaboratorA
  • Role2 =&gt; CollaboratorB

您的控制器需要接收列表,为了接收这些信息,我们需要两个类:

  • 将存储单个元素数据的类,将角色ID与协作者ID映射:

    public class RoleCollaborator {
    
        private Long roleId;
    
        private Long collaboratorId;
    
        public Long getRoleId() {
            return roleId;
        }
    
        public void setRoleId(Long roleId) {
            this.roleId = roleId;
        }
    
        public Long getCollaboratorId() {
            return collaboratorId;
        }
    
        public void setCollaboratorId(Long collaboratorId) {
            this.collaboratorId = collaboratorId;
        }
    
    }
    
  • 用于存储单个映射列表的包装类:

    public class RolesCollaborators {
    
        private List<RoleCollaborator> rolesCollaborators;
    
        public List<RoleCollaborator> getRolesCollaborators() {
            return rolesCollaborators;
        }
    
        public void setRolesCollaborators(List<RoleCollaborator> rolesCollaborators) {
            this.rolesCollaborators = rolesCollaborators;
        }
    
    }
    

接下来要做的是更改控制器,其中有两个方法,一个处理GET请求,另一个处理POST请求,因此接收表单数据。

在GET中:

public String projectCollaborators(@PathVariable Long projectId, Model model) {
    (... your code ...)

    model.addAttribute("project", project);

    // Add the next line to add the "rolesCollaborators" instance
    model.addAttribute("rolesCollaborators", new RolesCollaborators());

    return "project_collaborators";
}

如您所见,我们添加了一条将由百日咳模板使用的线。现在是角色和协作者的空列表的包装器,但如果需要编辑现有映射而不是添加新映射,则可以添加值。

在POST中:

// We changed the @ModelAttribute from Project to RolesCollaborators
public String projectCollaboratorsPost(@ModelAttribute RolesCollaborators rolesCollaborators, @PathVariable Long projectId, Model model) {
   (... your code ...)
}

此时,您的控制器已准备好接收从您的表单发送的信息,我们还需要修改。

<form th:action="@{'/project_collaborators/' + ${project.id}}" method="post" th:object="${rolesCollaborators}">
    <label th:text="'Edit Collaborators: ' + ${project.name}">Edit Collaborators: Website Project</label>
    <ul class="checkbox-list">

        <li th:each="a, stat : ${assignments}">
            <span th:text="${a.role.name}" class="primary">Developer</span>

            <div class="custom-select">
                <input type="hidden" th:id="rolesCollaborators[__${stat.index}__].roleId" th:name="rolesCollaborators[__${stat.index}__].roleId" th:value="${a.role.id}" />
                <span class="dropdown-arrow"></span>
                <select th:field="*{rolesCollaborators[__${stat.index}__].collaboratorId}">
                    <option th:each="collaborator : ${allCollaborators}" th:value="${collaborator.id}" th:text="${collaborator.name}">Michael Pemulis</option>
                </select>
            </div>
        </li>

    </ul>
    <div class="actions">
        <input type="submit" value="Save" class="button"/>
        <a href="#" class="button button-secondary">Cancel</a>
    </div>
</form>

这里有一些变化:

  • 正如我在异常原因中指出的那样,您需要将 th:object =“$ {project}”更改为 th:object =“ $ {rolesCollaborators}“,因为rolesCollaborator是您将从GET控制器方法接收值的实例名称,以及您将值发送到POST控制器方法的位置。
  • 我添加了一个隐藏的输入;此输入将存储将与用户使用 select 元素从界面中选取的协作者ID关联发送的角色ID。看一下使用的语法。
  • 我更改了 select 元素的 th:field 值,以引用我们在中使用的 rollesCollaborators 对象中的字段th:object =“$ {rolesCollaborators}”表单属性。这将在 RolesCollaborators 包装列表的 RoleCollaborator 元素中设置协作者的值。

通过这些更改,您的代码将起作用。当然,您可以通过其他一些修改来改进它,但我试图不引入更多修改来专注于您的问题。