从视图中的选择选项更新数据库模型中的列表项不起作用

时间:2019-03-01 22:04:47

标签: java spring spring-boot spring-mvc thymeleaf

这是普遍的问题。我有三种模型:项目,角色和协作者(下面列出)。从项目模型中可以看出,它包含需要的角色列表和项目上的协作者列表。创建项目时,它只会添加所需的角色,而将协作者列表保留为空,因此用户可以根据需要的角色随后添加协作者。在尝试向项目中添加新的协作者时,我遇到了一些不确定的解决方法。请参见下面的ProjectControllerproject_collaborator视图,以帮助解决问题。

问题1

  • 用户从多个选项的下拉菜单中选择协作者。当他们单击“保存”时,我希望使用多个下拉菜单中指定的值来更新协作者列表。但是,发生这种情况时,我会收到此错误:

Error: Problem 1

  • 现在这不是实际错误,但是我不明白为什么基于我的代码会删除项目角色和合作者列表。这是我想到可能导致第二个问题的解决方案的时候。

问题2:

  • 我想,我忘了添加一个包含RolesNeeded字段列表的隐藏输入字段。但这又导致了转换问题,我无法将字符串转换为列表(我尝试过)。

在这一点上,我不确定是否可以解决我的问题,也许我需要对该应用程序进行重新设计。控制器中用于此特定视图的方法为:changeCollaboraters()updateCollaborators()。我还包括了它的外观。如果有人可以帮助,那就太好了。

Project.java

@Entity
public class Project {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotNull
private String name;

@NotNull
private String desc;

@NotNull
private String status;

@ManyToMany
@LazyCollection(LazyCollectionOption.FALSE)
private List<Role> rolesNeeded = new ArrayList<>();

@ManyToMany
@LazyCollection(LazyCollectionOption.FALSE)
private List<Collaborator> collaborators = new ArrayList<>();

public Project() {}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getDesc() {
    return desc;
}

public void setDesc(String desc) {
    this.desc = desc;
}

public String getStatus() {
    return status;
}

public void setStatus(String status) {
    this.status = status;
}

public List<Role> getRolesNeeded() {
    return rolesNeeded;
}

public void setRolesNeeded(List<Role> rolesNeeded) {
    this.rolesNeeded = rolesNeeded;
}

public List<Collaborator> getCollaborators() {
    return collaborators;
}

}

ProjectController.java

Controller
public class ProjectController {

@Autowired
private ProjectServiceImpl projectService;

@Autowired
private RoleServiceImpl roleService;

@Autowired
private CollaboratorServiceImpl collaboratorService;

@RequestMapping("/projects")
public String getProjects(ModelMap model) {
    List<Project> projects = projectService.findAll();
    model.put("projects", projects);

    return "index";
}

@RequestMapping("/projects/create")
public String addProject(ModelMap model) {

    if (!model.containsAttribute("project")) {
        model.put("project", new Project());
    }

    model.put("roles", roleService.findAll());

    return "edit_project";
}

@RequestMapping(value = "/projects", method = RequestMethod.POST)
public String addProject(@Valid Project project, BindingResult result, RedirectAttributes redirectAttributes) {

    if (result.hasErrors()) {

        result.getAllErrors().forEach(System.out::println);
        return "redirect:/projects/create";
    }

    projectService.save(project);

    return "redirect:/projects";
}

@RequestMapping("/projects/{id}")
@Transactional
public String viewProject(@PathVariable Long id, ModelMap model) {
    Project p = projectService.findById(id);
    model.put("project", p);
    model.put("roleToC", mapRoles(p.getRolesNeeded(), p.getCollaborators()));


    return "project_detail";
}

@RequestMapping("/projects/{id}/collaborators")
@Transactional
public String changeCollaborators(@PathVariable Long id, ModelMap model) {
    Project p = projectService.findById(id);
    model.put("project", p);
    model.put("roleToC", mapRoles(p.getRolesNeeded(), p.getCollaborators()));

    model.put("collaborators", collaboratorService.findAll());
    model.put("action", String.format("/projects/%s", id));

    return "project_collaborators";
}

@RequestMapping(value = "/projects/{id}", method = RequestMethod.POST)
public String updateCollaborators(@Valid Project project, BindingResult result, RedirectAttributes redirectAttributes) {

    if (result.hasErrors()) {
        result.getAllErrors().forEach(System.out::println);
        return String.format("redirect:/projects/{id}/collaborators");
    }

    projectService.save(project);

    return String.format("redirect:/projects/%s", project.getId());
}


private Map<Role, Collaborator> mapRoles(List<Role> roles, List<Collaborator> collaborators) {
    Map<Role, Collaborator> map = new HashMap<>();
    for (Role role : roles) {
        boolean roleFound = false;
        Collaborator collaborator = null;
        for (Collaborator c : collaborators) {
            if (c.getRole() == role) {
                roleFound = true;
                collaborator = c;
                break;
            }
        }
        if (roleFound) {
            map.put(role, collaborator);
        } else {
            map.put(role, null);
        }
        roleFound = false;
    }

    return map;
}

}

project_collaborators.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <head th:replace="base :: head('project_collaborators')"></head>
    <body>
        <header th:replace="base :: header"></header>
        <nav>
            <ul>
                <li class="selected"><a th:href="@{/projects}">Projects</a></li>
                <li><a th:href="@{/collaborators}">Collaborators</a></li>
                <li><a th:href="@{/roles}">Roles</a></li>
            </ul>
        </nav>
        <section>
            <div class="container wrapper">
                <form th:action="@{${action}}" th:method="post" th:object="${project}">
                    <input type="hidden" th:field="*{desc}">
                    <input type="hidden" th:field="*{status}">
                    <input type="hidden" th:field="*{name}">
                    <label th:text="${'Edit Collaborators: ' + project.name}">Edit Collaborators: Website Project</label>
                    <ul class="checkbox-list">
                        <li th:each="element : ${roleToC}"><span class="primary" th:text="${element.key.name}">Developer</span>
                            <div class="custom-select">
                                <span class="dropdown-arrow"></span>
                                <select th:field="*{collaborators}">
                                    <option th:each="c : ${collaborators}" th:if="${#strings.equals(c.role.name, element.key.name)}" th:value="${c.id}" th:text="${c.name}" >Michael Pemulis</option>
                                </select>
                            </div>
                        </li>
                    </ul>
                    <div class="actions">
                        <input type="submit" value="Save" class="button">
                        <a th:href="@{/projects}" class="button button-secondary">Cancel</a>
                    </div>
                </form>
            </div>
        </section>
    </body>
</html>

project_collaborator view

0 个答案:

没有答案