简体   繁体   English

Spring MVC / JSP-如何将对象的嵌套列表从选择表单传递给控制器

[英]Spring MVC / JSP - How to pass nested list of object to controller from a select form

I am using Spring MVC with JSP. 我在JSP中使用Spring MVC。

I have a User entity which contains a list of Group entities. 我有一个用户实体,其中包含一个组实体列表。 The relationship is Many-to-Many (a Group entity contains a list of User entities). 关系是多对多的(一个组实体包含一个用户实体列表)。

In my user controller I have a method for returning the add user page with an empty User entity and a list of available Group entities. 在我的用户控制器中,我有一种返回带有空用户实体和可用组实体列表的添加用户页面的方法。

@RequestMapping(value = "/add", method = RequestMethod.GET)
public ModelAndView loadUserAdd() {
    ModelAndView mv = new ModelAndView("user/userAdd");
    mv.addObject("user", new User());
    try {
        mv.addObject("groups", gr.listGroups());
    } catch (TestException e) {
        mv.addObject("error", e.getMessage());
        e.printStackTrace();
    }

    return mv;
}

On the userAdd page, I want to select the group(s) the user will have from the list of the available groups. 在userAdd页面上,我想从可用组列表中选择用户将拥有的组。

<div class="row">
    <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">
        <select id="availableGroups" class="form-control" multiple onclick="shuttle('availableGroups', 'selectedGroups')">
            <c:forEach items="${groups}" var="group">
                <option value="${group.id}">${group.id}: ${group.name}</option>
            </c:forEach>
        </select>
    </div>
    <div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">
        <select id="selectedGroups" class="form-control" multiple onclick="shuttle('selectedGroups', 'availableGroups')">
            <c:forEach var="group" items="${user.groups}" varStatus="status">
                <option value="${group.id}">${group.id}: ${group.name}</option>
            </c:forEach>
        </select>
    </div>
</div>

Note, the 'shuttle' function moves a group from one select element to the other. 注意,“穿梭”功能将一组从一个选择元素移到另一个。 Eg from the available groups to the selected groups or vice versa. 例如,从可用组到所选组,反之亦然。 This works. 这可行。

On submit, I want to have the selected groups set in the user entity so that it will arrive in the addUser method. 在提交时,我希望在用户实体中设置选定的组,以便它将到达addUser方法中。

@RequestMapping(value = "/add", method = RequestMethod.POST)
public ModelAndView addUser(@ModelAttribute("user") User user) {

Instead on submit, the user entity contains a null list of groups. 而是在提交时,用户实体包含组的空列表。 I'm sure my JSP is wrong so it would be great if someone could point me in the right direction. 我确信我的JSP是错误的,因此如果有人可以向我指出正确的方向,那就太好了。 Any advice on improvements would be good as I'm doing this as a learning exercise. 关于改进的任何建议都将是不错的选择,因为我将其作为学习练习来进行。 Thanks. 谢谢。

A college suggested a way to solve this question. 一所大学提出了解决这个问题的方法。 The solution offered uses a single select field rather than two select fields with a shuttle moving values from available to selected and vice versa. 所提供的解决方案使用单个选择字段,而不是两个选择字段,同时将数值从可用位置移动到选定位置,反之亦然。

In the JSP, I've replaced both select fields with just one: 在JSP中,我仅用一个替换了两个选择字段:

<div class="row">
    <div class="col-xs-3 col-sm-3 col-md-3 col-lg-3">
        Groups
    </div>
    <div class="col-xs-9 col-sm-9 col-md-9 col-lg-9">
        <form:select
                path="groups"
                items="${availableGroups}"
                multiple="true"
                itemValue="id"
                itemLabel="name"
                class="form-control" />
    </div>
</div>

This form:select iterates over the available groups and creates a option element for each. 这种形式:select遍历可用组,并为每个组创建一个option元素。 The select attributes are: 选择属性是:
path - uses the value 'groups' to map to the getGroups getter method on the user entity in the view model (modelAndView.addObject("users", users);). path-使用值'groups'映射到视图模型中用户实体(modelAndView.addObject(“ users”,users);)上的getGroups getter方法。 items - is the list of all available groups in the system. items-是系统中所有可用组的列表。 This is set in the model from the controller. 这是在控制器的模型中设置的。 See note about this below. 请参阅下面的注释。 itemValue - is the value which will become the select's option's value. itemValue-是将成为选择选项的值的值。 The 'id' maps to the getId getter method of the current group. “ id”映射到当前组的getId getter方法。 itemLabel - is the value which will become the select's option's visible label. itemLabel-是将成为选项的可见标签的值。 The 'name' maps to the getName getter method of the current group. “名称”映射到当前组的getName getter方法。 The form:select also marks options as selected if the user has them set. 如果用户设置了选项,则form:select也将选项标记为选中。

Here is an example output where the groups are 1,2,3,4 (both in id and name) and the user has group 1,2. 这是一个示例输出,其中组是1,2,3,4(在ID和名称中都包括在内),而用户具有组1,2。

  <div class="col-xs-9 col-sm-9 col-md-9 col-lg-9">
    <select id="groups" name="groups" class="form-control" multiple="multiple">
      <option value="1" selected="selected">1</option>
      <option value="2" selected="selected">2</option>
      <option value="3">3</option>
      <option value="5">4</option>
    </select>
    <input type="hidden" name="_groups" value="1"/>
  </div>

To make 'availableGroups' available I've used: 为了使“ availableGroups”可用,我使用了:

@ModelAttribute("availableGroups")
public List<Group> initializeGroups() {
    return us.listGroups();
}

This makes the list of available-groups available to each view of the controller. 这使可用组列表可用于控制器的每个视图。

On submit, to update the user with the selected groups (either adding or removing groups as this works on edit too), I've used a Converter (org.springframework.core.convert.converter.Converter). 在提交时,要用选定的组更新用户(添加或删除组,因为这也可以在编辑时使用),我使用了Converter(org.springframework.core.convert.converter.Converter)。

@Component
public class GroupConverter implements Converter<String, Group> {
    @Autowired
    GroupService groupService;
    public User convert(String element) {
        User user = null;
        if(element != null) {
            int id = Integer.parseInt(element);
            user = userService.fetchUser(id);
        }
        return user;
    }
}

The Converter takes the id of the group and gets it from the data source then magically sets it in the user entity before the controller is called. 转换器获取组的ID并从数据源获取它,然后在调用控制器之前在用户实体中对其进行魔术设置。

Converters are set on the WebMvcConfigurationSupport... 转换器在WebMvcConfigurationSupport上设置。

@Autowired
GroupConverter groupConverter;

@Override
public void addFormatters(FormatterRegistry registry) {
    registry.addConverter(groupConverter);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM