2016-07-28 7 views
0

Мне нужно выбрать значения из одного массива и назначить его другому массиву. Использование Spring Thymeleaf. Не знаю, как получить эти выбранные значения. Мои классы:Вход в массив 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> 

Как вы можете видеть, что я хочу, чтобы пользователь может выбрать для каждой роли (roleNeeded) любого сотрудника из (allCollaborators) и сохраните это назначение в списке (назначения).

И я получаю сообщение об ошибке:

ava.lang.IllegalStateException: Ни BindingResult, ни простой объект целевого для имени боб «а» доступен как атрибут запроса

Так вопрос: как чтобы решить эту проблему, назначьте значения из одного массива в другой в шаблоне и извлеките эти значения в моем контроллере.

ответ

1

Причиной исключения

IllegalStateException вы получаете, потому что -й: в вашей выберите элемент должен быть связан с формой поля = «$ {A.id}»th: object = "$ {project}" элемент; поле th: поле атрибут должен ссылаться на фактическое поле в проекте экземпляра (также вам нужно написать th: field = "* {fieldName}"). Это должно исправить исключение, которое вы получаете, но не решит всю вашу проблему, так как вторая его часть связана с , как заставить значения попасть в ваш контроллер, что я объясню дальше.

Отправка значения в контроллер

Чтобы получить значения в контроллер нужно будет сделать несколько изменений. Поскольку я действительно не знаю код вашего Project, я изменю несколько вещей, чтобы вы могли понять, как приспособить этот простой пример к вашему конкретному случаю.

Во-первых, я понимаю, что вы хотите сделать отношения как следующее в форму:

  • Role1 => CollaboratorA
  • роль2 => CollaboratorB

Ваш контроллер должен получать и для получения этой информации нам нужны два класса:

  • Класс, который будет хранить индивидуальные данные элемента, отображающий идентификатор роли с сотрудником 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, и, таким образом, получает ваши данные формы.

В ГЭТ одном:

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"; 
} 

Как вы можете видеть, мы добавили строку, которая будет использоваться в шаблоне thymeleaf. Прямо сейчас это оболочка пустого списка ролей и соавторов, но вы можете добавлять значения, если вам нужно редактировать существующие сопоставления вместо добавления новых.

В ПОСТ одном:

// 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 = "$ {roleCollaborators}", поскольку roleCollaborator - это имя экземпляра, откуда вы получите значения из вашего метода контроллера GET и где вы будете отправлять значения в свой метод контроллера POST.
  • Я добавил скрытый ввод; этот ввод сохранит идентификатор роли, который будет отправлен в ассоциации с идентификатором соавтора, который пользователь выбирает из интерфейса, используя . Выберите элемент. Взгляните на используемый синтаксис.
  • Я изменил й: поле значение вашего выбрать элемент для обозначения поля в rollesCollaborators объекта мы используем в ом: объект = «$ {rolesCollaborators}» атрибут формы. Это установит значение соавтора в элементе RoleCollaborator элемента RolesCollaborators.

С этими изменениями ваш код будет работать. Конечно, вы можете улучшить его с некоторыми другими изменениями, но я попытался не вводить больше изменений, чтобы сосредоточиться на вашей проблеме.

+0

Большое спасибо, отлично работает! – zzheads

+0

@zzheads Рад слышать. Не забудьте принять ответ, пожалуйста;). – BitExodus

+0

Конечно, все. Не могли бы вы проверить мой другой вопрос о том же проекте?) здесь: http://stackoverflow.com/questions/38693971/input-type-date-thymeleaf – zzheads

Смежные вопросы