Comment faire pour lier un objet de la liste avec thymeleaf?

J'ai beaucoup de difficulté avec la Publication d'un formulaire pour le contrôleur, qui doit contenir tout simplement une arraylist d'objets que l'utilisateur peut modifier.

Le formulaire se charge correctement, mais quand il est affiché, il ne semble jamais vraiment publier quoi que ce soit.

Voici mon formulaire:

<form action="#" th:action="@{/query/submitQuery}" th:object="${clientList}" method="post">

<table class="table table-bordered table-hover table-striped">
<thead>
    <tr>
        <th>Select</th>
        <th>Client ID</th>
        <th>IP Addresss</th>
        <th>Description</th>            
   </tr>
 </thead>
 <tbody>     
     <tr th:each="currentClient, stat : ${clientList}">         
         <td><input type="checkbox" th:checked="${currentClient.selected}" /></td>
         <td th:text="${currentClient.getClientID()}" ></td>
         <td th:text="${currentClient.getIpAddress()}"></td>
         <td th:text="${currentClient.getDescription()}" ></td>
      </tr>
  </tbody>
  </table>
  <button type="submit" value="submit" class="btn btn-success">Submit</button>
  </form>

Ci-dessus fonctionne très bien, il charge la liste correctement. Cependant, quand je POSTE, elle retourne un objet vide (de taille 0). Je crois que c'est en raison de l'absence de th:field, mais de toute façon, ici, est contrôleur de la méthode POST:

...
private List<ClientWithSelection> allClientsWithSelection = new ArrayList<ClientWithSelection>();
//GET method
...
model.addAttribute("clientList", allClientsWithSelection)
....
//POST method
@RequestMapping(value="/submitQuery", method = RequestMethod.POST)
public String processQuery(@ModelAttribute(value="clientList") ArrayList clientList, Model model){
    //clientList== 0 in size
    ...
}

J'ai essayé d'ajouter un th:field mais peu importe ce que je fais, il provoque une exception.

J'ai essayé:

...
<tr th:each="currentClient, stat : ${clientList}">   
     <td><input type="checkbox" th:checked="${currentClient.selected}"  th:field="*{}" /></td>

    <td th th:field="*{currentClient.selected}" ></td>
...

Je ne peux pas accéder currentClient (erreur de compilation), je ne peux même pas sélectionner clientList, il me donne des options comme get(), add(), clearAll() etc, de sorte qu'il des choses qu'elle devrait avoir un tableau, cependant, je ne peux pas passer un tableau.

J'ai aussi essayé d'utiliser quelque chose comme th:field=${}, cela provoque une exception d'exécution

J'ai essayé

th:field = "*{clientList[__currentClient.clientID__]}" 

mais aussi erreur de compilation.

Des idées?


Mise à JOUR 1:

Tobias a suggéré que j'ai besoin d'envelopper ma liste dans une wraapper. Donc, c'est ce que j'ai fait:

ClientWithSelectionWrapper:

public class ClientWithSelectionListWrapper {

private ArrayList<ClientWithSelection> clientList;

public List<ClientWithSelection> getClientList(){
    return clientList;
}

public void setClientList(ArrayList<ClientWithSelection> clients){
    this.clientList = clients;
}
}

Ma page:

<form action="#" th:action="@{/query/submitQuery}" th:object="${wrapper}" method="post">
....
 <tr th:each="currentClient, stat : ${wrapper.clientList}">
     <td th:text="${stat}"></td>
     <td>
         <input type="checkbox"
                th:name="|clientList[${stat.index}]|"
                th:value="${currentClient.getClientID()}"
                th:checked="${currentClient.selected}" />
     </td>
     <td th:text="${currentClient.getClientID()}" ></td>
     <td th:text="${currentClient.getIpAddress()}"></td>
     <td th:text="${currentClient.getDescription()}" ></td>
 </tr>

Au-dessus de charge très bien:
Comment faire pour lier un objet de la liste avec thymeleaf?

Puis mon contrôleur:

@RequestMapping(value="/submitQuery", method = RequestMethod.POST)
public String processQuery(@ModelAttribute ClientWithSelectionListWrapper wrapper, Model model){
... 
}

La page se charge correctement, les données s'affichent comme prévu. Si je poste le formulaire sans aucune sélection, j'obtiens ceci:

org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 0): Property or field 'clientList' cannot be found on null

Pas sûr pourquoi elle se plaindre

(Dans la Méthode qu'il a: model.addAttribute("wrapper", wrapper);)

Comment faire pour lier un objet de la liste avec thymeleaf?

Si je puis faire une sélection, c'est à dire cocher la première entrée:

There was an unexpected error (type=Bad Request, status=400).
Validation failed for object='clientWithSelectionListWrapper'. Error count: 1

Je devine que mon POSTE de contrôleur n'est pas le clientWithSelectionListWrapper. Je ne sais pas pourquoi, depuis que j'ai mis de l'objet wrapper pour être posté à l'arrière via le th:object="wrapper" dans l'en-tête du FORMULAIRE.


Mise à JOUR 2:

J'ai fait quelques progrès! Enfin, le formulaire soumis est récupéré par la méthode POST dans le contrôleur. Cependant, toutes les propriétés semblent être nulle, sauf si l'objet a été cochée ou non. J'ai fait plusieurs changements, c'est la façon dont il est à la recherche:

<form action="#" th:action="@{/query/submitQuery}" th:object="${wrapper}" method="post">
....
 <tr th:each="currentClient, stat : ${clientList}">
     <td th:text="${stat}"></td>
     <td>
         <input type="checkbox"
                th:name="|clientList[${stat.index}]|"
                th:value="${currentClient.getClientID()}"
                th:checked="${currentClient.selected}"
                th:field="*{clientList[__${stat.index}__].selected}">
     </td>
     <td th:text="${currentClient.getClientID()}"
         th:field="*{clientList[__${stat.index}__].clientID}"
         th:value="${currentClient.getClientID()}"
     ></td>
     <td th:text="${currentClient.getIpAddress()}"
         th:field="*{clientList[__${stat.index}__].ipAddress}"
         th:value="${currentClient.getIpAddress()}"
     ></td>
     <td th:text="${currentClient.getDescription()}"
         th:field="*{clientList[__${stat.index}__].description}"
         th:value="${currentClient.getDescription()}"
     ></td>
     </tr>

J'ai également ajouté un défaut param-moins de constructeur de ma classe wrapper et ajouté un bindingResult paramètre à la méthode POST (pas sûr si nécessaire).

public String processQuery(@ModelAttribute ClientWithSelectionListWrapper wrapper, BindingResult bindingResult, Model model)

Ainsi lorsqu'un objet est affiché, c'est la façon dont il est à la recherche:
Comment faire pour lier un objet de la liste avec thymeleaf?

Bien sûr, la systemInfo est censé être nul (à ce stade), mais le clientID est toujours 0, et ipAddress/Description toujours null. Sélectionné booléenne est correct, bien que pour toutes les propriétés. Je suis sûr que j'ai fait une erreur sur l'une des propriétés quelque part. De retour de l'enquête.


Mise à JOUR 3:

Ok j'ai réussi à remplir toutes les valeurs correctement! Mais j'ai dû changer mon td pour inclure une <input /> qui n'est pas ce que je voulais... Néanmoins, les valeurs sont peupler correctement, ce qui suggère looks du printemps pour une balise input peut-être pour le mappage de données?

Voici un exemple de la façon dont j'ai changé le clientID données de la table:

<td>
 <input type="text" readonly="readonly"                                                          
     th:name="|clientList[${stat.index}]|"
     th:value="${currentClient.getClientID()}"
     th:field="*{clientList[__${stat.index}__].clientID}"
  />
</td>

Maintenant, j'ai besoin de comprendre comment les afficher sur la plaine de données, idéalement sans la présence d'une zone de saisie...

  • La liaison fonctionne qu'avec input éléments, avec quelque chose de poste client à l'arrière du serveur. D'autres cadres peuvent utiliser une sorte d'état d'affichage ou de la session et de cacher les détails de la part du développeur, mais autant que je sache timeleaf fais pas le faire. Dans ce cas particulier, vous pouvez lier les valeurs de champs cachés.
  • ouais, vous avez raison, littéralement la trouve 30secs avant votre commentaire. Ouais, doit être un thymeleafff chose, je suis sûr que lorsque j'ai fait quelque chose de similaire dans asp.net il ramassa directement. De toute façon, je vais certainement faire besoin d'écrire cela comme un rappel!
InformationsquelleAutor benscabbia | 2016-04-08