Вот общая проблема.У меня есть три модели: Project, Role & Collaborator (перечислены ниже).Как видно из модели проекта, он содержит список ролей, необходимых и список соавторов проекта.Когда вы создаете проект, он только добавляет необходимые роли и оставляет список соавторов пустым, чтобы пользователь мог впоследствии добавить соавторов в зависимости от того, какие роли необходимы.При попытке добавить новых соавторов в проект, я сталкиваюсь с несколькими проблемами, для которых я не уверен, что это обходной путь.См. ProjectController
и project_collaborator
представления ниже, чтобы помочь с решением проблем.
ПРОБЛЕМА 1 :
- Пользователь выбирает соавторов из выпадающего спискаменю из нескольких вариантов.Когда они нажмут кнопку «Сохранить», я бы хотел, чтобы список соавторов обновлялся значениями, указанными в нескольких раскрывающихся меню.Но когда это происходит, я получаю эту ошибку:
Ошибка: проблема 1
- Теперь это не фактическая ошибка, но я неНе понимаю, почему роли проекта и списки соавторов будут удалены на основе моего кода.Это когда я подумал о возможном решении, которое привело бы ко второй проблеме.
ПРОБЛЕМА 2:
- Я подумал, я забыл добавитьскрытое поле ввода, содержащее список полей roleNeeded.Но это снова приводит к проблеме преобразования, когда я не могу преобразовать строку в список (я пытался).
На данный момент, я не уверен, есть ли решение моей проблемыи, возможно, мне нужно изменить дизайн для этого приложения.Методы, используемые в контроллере для этого конкретного представления: 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