2016-07-28 8 views
0

Ich brauche Werte von einem Array zu wählen und es anderen Array zuweisen. Unter Verwendung des Frühlings-Thymoleaf. Keine Ahnung, wie diese ausgewählten Werte abgerufen werden. Meine Klassen:Eingang in Array 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() {}.... 

Meine Controller:

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

Und Vorlage:

  <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> 

Wie Sie sehen, ich möchte Benutzer für jede Rolle wählen lassen (roleNeeded) alle Mitarbeiter aus (allCollaborators) und behalte diese Zuweisungen in Liste (Zuweisungen).

Und ich bekomme Fehlermeldung:

ava.lang.IllegalStateException: Weder BindingResult noch ebenes Ziel Objekt für Bohnen Namen 'a' als Anfrage Attribut verfügbar

So Frage lautet: Wie Um es zu lösen, weisen Sie in der Vorlage Werte von einem Array zum anderen zu und rufen Sie diese Werte in meinem Controller ab.

Antwort

1

Die Ursache der Ausnahme

Die Illegal Sie bekommen ist, weil th: field = "$ {a.id}" in Ihrem Element auswählen müssen auf die Form bezogen werden th: object = "$ {project}" Element; Das th: Feld Attribut muss sich auf ein tatsächliches Feld in der Projekt Instanz beziehen (auch müssen Sie schreiben th: field = "* {fieldName}"). Das sollte die Ausnahme beheben, die Sie bekommen, wird aber nicht Ihr gesamtes Problem lösen, da der zweite Teil davon mit in Verbindung steht, wie Sie die Werte in Ihren Controller bekommen, was ich als nächstes erklären werde.

die Werte auf dem Controller gesendet

Um die Werte in Ihrem Controller erhalten Sie ein paar Änderungen vornehmen müssen. Da ich nicht wirklich den Code Ihrer Projekt Klasse kenne, werde ich ein paar Dinge ändern, so dass Sie in der Lage sein werden, herauszufinden, wie Sie dieses einfache Beispiel an Ihren speziellen Fall anpassen können.

Erstens, ich verstehe Sie eine Beziehung wie folgt in Ihrem Formular machen wollen:

  • Role1 => CollaboratorA
  • Role2 => CollaboratorB

Ihr Controller muss ein erhalten Liste und um diese Informationen zu erhalten, brauchen wir zwei Klassen:

  • Die Klasse, die die einzelne Elementdaten speichert wird, Abbilden eine Rolle-ID mit der Kollaborateur 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; 
        } 
    
    } 
    
  • eine Wrapper-Klasse eine Liste einzelner Zuordnungen zu speichern:

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

Als nächstes ändern Sie Ihre Controller, wo Sie zwei Methoden haben, eine, die GET-Anfragen bearbeitet, und eine andere, die die POST-Anfragen behandelt und so Ihre Formulardaten empfängt.

Im GET ein:

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

Wie Sie sehen können, haben wir eine Linie, die durch die thymeleaf Vorlage verwendet wird. Im Moment ist ein Wrapper mit einer leeren Liste von Rollen und Mitarbeitern vorhanden, aber Sie können Werte hinzufügen, wenn Sie vorhandene Zuordnungen bearbeiten müssen, anstatt neue hinzuzufügen.

Im POST ein:

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

An diesem Punkt wird der Controller aus dem Formular gesendet, um die Informationen zu erhalten vorbereitet, dass wir ändern müssen auch.

<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> 

Hier gibt es ein paar Änderungen:

  • Als ich die Ursache für die Ausnahme in darauf hingewiesen Sie brauchen th zu ändern: Objekt = "$ {Projekt}"-th: object = "$ {rolesCollaborators}", als rolesCollaborator ist der Instanzname, von dem Sie die Werte von Ihrer GET-Controller-Methode erhalten und wo Sie die Werte an Ihre POST-Controller-Methode senden werden.
  • Ich habe einen versteckten Eingang hinzugefügt; Diese Eingabe speichert die Rollen-ID, die in Verbindung mit der Kollaborator-ID gesendet wird, die der Benutzer mit dem select Element aus der Schnittstelle auswählt. Schau dir die Syntax an.
  • Ich habe den th: Feld Wert Ihrer wählen Element in dem rollesCollaborators auf ein Feld verweisen Objekt, das wir in th verwenden: Objekt = "$ {rolesCollaborators}" Form Attribut. Das wird den Wert des Mitarbeiters in dem RoleCollaborator Element der RolesCollaborators verpackte Liste festlegen.

Mit diesen Änderungen wird Ihr Code funktionieren. Natürlich können Sie es mit einigen anderen Modifikationen verbessern, aber ich habe versucht, keine weiteren Modifikationen einzuführen, um sich auf Ihr Problem zu konzentrieren.

+0

Vielen Dank, funktioniert perfekt! – zzheads

+0

@zzheads Schön zu hören. Vergiss nicht, die Antwort zu akzeptieren, bitte;). – BitExodus

+0

Sicher, fertig. Kannst du bitte meine andere Frage zum selben Projekt überprüfen?) hier: http://stackoverflow.com/questions/38693971/input-type-date-thymeleaf – zzheads