2014-03-07 8 views
11

Ich ändere diese Frage total, als Teil davon wurde here mit großer Hilfe von Avnish beantwortet! Tom schickte mich in die richtige Richtung, also danke Tom!thymeleaf mehrere ausgewählt am bearbeiten

Mein Problem ist, dass ich nicht weiß, wie man Thymeleaf anweist, Objektelemente beim Editieren vorzuwählen.

Lassen Sie mich Ihnen:

looks like this

Diese Lösung funktioniert:

 <select class="form-control" id="parts" name="parts" multiple="multiple" > 
      <option th:each="part : ${partsAtribute}" 
        th:selected="${servisAttribute.parts.contains(part)}" 
        th:value="${part.id}" 
        th:text="${part.name}">Part name</option> 
     </select> 

Ich habe versucht, dies:

  <select class="form-control" th:field="*{parts}" multiple="multiple" > 
      <option th:each="part : ${partsAtribute}" 
        th:field="*{parts}" 
        th:value="${part.id}" 
        th:text="${part.name}">Part name</option> 
      </select> 

nicht funktionierte. Ich habe es auch versucht:

  <select class="form-control" th:field="*{{parts}}" multiple="multiple" > 
      <option th:each="part : ${partsAtribute}" 
        th:field="*{parts}" 
        th:value="${part.id}" 
        th:text="${part.name}">Part name</option> 
      </select> 

hat auch nicht funktioniert. Ich habe versucht, th zu entfernen: field = "* {parts}" aus dem Options-Tag, das gleiche Ergebnis ..

Wenn ich th ändern: Wert zu $ ​​{part} funktioniert es, aber dann sendet es keine Zeichenfolge von IDs wie [2,4,5,6, ...], aber Teilinstanzen wie [Teil @ 43b45j, Teil @ we43y7, ...] ...

UPDATE: Ich merke nur, dass dies funktioniert, wenn nur ein Teil ausgewählt ist:

<select class="form-control" th:field="*{parts}" multiple="multiple" > 
      <option th:each="part : ${partsAtribute}" 
        th:field="*{parts}" 
        th:value="${part.id}" 
        th:text="${part.name}">Part name</option> 
      </select> 

Wenn mehrere Teile ausgewählt werden, funktioniert es nicht ...

Antwort

11

Nach der Diskussion über die Thymeleaf Forum, implementiert ich ein voll funktionierendes Beispiel bei https://github.com/jmiguelsamper/thymeleafexamples-selectmultiple

Ich denke, dass das einzige Problem mit Ihrem endgültigen Code ist, dass Sie doppelte Klammer-Syntax zu verwenden, haben die conversionService aufzurufen:

th:value="${{part}}" 

Es ist auch wichtig, die richtigen equals() - und hashcode() - Methoden in Ihrer Part-Klasse zu implementieren, um einen korrekten Vergleich zu gewährleisten.

Ich hoffe, mein Beispiel hilft anderen Benutzern mit ähnlichen Problemen in der Zukunft.

+4

Dies ist ein Muss: "Es ist auch wichtig, die richtigen equals() - und hashcode() -Methoden in Ihrer Part-Klasse zu implementieren, um einen korrekten Vergleich zu gewährleisten." – Blejzer

7

Sie nicht th:selected brauchen, wenn 01 mitnormalerweise. Thymeleaf überprüft automatisch die Werte der einzelnen <option> in der <select>, auch wenn es multiple

ist Das Problem liegt in dem Wert. Sie durchlaufen über parts, aber der Wert jeder Option ist part.id. So vergleichen Sie Instanzen von Teil mit der ID von Teil (soweit ich sehen kann).

Thymeleaf berücksichtigt jedoch auch Instanzen von PropertyEditor (es wird org.springframework.web.servlet.tags.form.SelectedValueComparator wiederverwendet).

Dies wird verwendet, wenn die Objekte mit den Werten der Optionen verglichen werden. Es konvertiert die Objekte in ihren Textwert (ihre ID) und vergleicht dies mit dem Wert.

<select class="form-control" th:field="*{parts}" multiple="multiple" > 
     <option th:each="part : ${partsAttribute}" 
       <!-- 
        Enable the SpringOptionFieldAttrProcessor . 
        th:field value of option must be equal to that of the select tag 
       --> 
       th:field="*{parts}" 
       th:value="${part.id}" 
       th:text="${part.name} + ${part.serial}">Part name and serial No.      
     </option> 
</select> 

Eigenschaftseditor

definieren PropertyEditor für die Teile. Der PropertyEditor wird aufgerufen, wenn die Werte verglichen und die Teile an das Formular gebunden werden.

@Controller 
public class PartsController { 
    @Autowired 
    private VehicleService vehicleService; 

    @InitBinder(value="parts") 
    protected void initBinder(final WebDataBinder binder) { 
     binder.registerCustomEditor(Part.class, new PartPropertyEditor()); 
    } 

    private static class PartPropertyEditor extends PropertyEditorSupport { 
     @Override 
     public void setAsText(String partId) { 
      final Part part = ...; // Get part based on the id 
      setValue(part); 
     } 

     /** 
     * This is called when checking if an option is selected 
     */ 
     @Override 
     public String getAsText() { 
      return ((Part)getValue()).getId(); // don't forget null checking 
     } 
    } 
} 

Schauen Sie sich auch ConvertingPropertyEditorAdapter an. Converter Instanzen, die in der conversionService registriert sind, sind heute im Frühjahr mehr bevorzugt.

+0

Sie für diese große Antwort danken. Ich habe Anpassungen vorgenommen und Ihren Vorschlag umgesetzt, und natürlich funktioniert es immer noch nicht. Ich bekomme keine Fehler oder irgendetwas, nur ... Kannst du mir sagen, wo ich nach Beispielen oder Dokumentation zu Konvertern suchen soll? Alles, was ich gefunden habe, ist Spring API ... Nur so kann ich verstehen, wie dieser Custom Editor funktioniert soll tun ... – Blejzer

+0

Ich habe endlich einen Konverter implementiert. Es hat einige Zeit gedauert, aber es funktioniert. Danke dafür. Ich habe versucht, mit benutzerdefinierten Eigenschafteneditor und es funktioniert auch gut. Ich kann Thymeleaf einfach nicht zur Arbeit bringen. Ich werde meine Frage so bearbeiten, dass Sie und andere sehen können ... – Blejzer

0
<select th:field="*{groupId}" > 
    <option th:each="group :${grouptype}" 
      th:value="${{group.groupId}}" 
      th:text="${group.Desc}"> 

    </option> 
</select> 

Einfach wählen Beispiel

0

Dies funktioniert für mich:

Ein Tierarzt viele Spezialitäten hat.

Controller:

@RequestMapping(value = "/vets/{vetId}/edit", method = RequestMethod.GET) 
public ModelAndView editVet(@PathVariable("vetId") int ownerId/*, Model model*/) { 

    ModelAndView mav = new ModelAndView("vets/vetEdit"); 

    mav.addObject("vet", this.vets.findById(ownerId)); 

    mav.addObject("allSpecialties", this.specialities.findAll());   

    return mav;  
} 

Ansicht (mit th: Auswahl):

<select id="specialities" class="form-control" multiple> 
      <option th:each="s : ${allSpecialties}"           
        th:value="${s.id}" 
        th:text="${s.name}" 
        th:selected="${vet.specialties.contains(s)}"> 
      </option> 
     </select> 

Ansicht (mit th: Feld):

<form th:object="${vet}" class="form-horizontal" id="add-vet-form" method="post"> 
    <div class="form-group has-feedback"> 
     <select th:field="*{specialties}" class="form-control" multiple> 
      <option th:each="s : ${allSpecialties}"           
        th:value="${s.id}" 
        th:text="${s.name}" 
        >    
      </option> 
     </select>   
    </div> 

Und ich habe zu definieren Specialty findOne(@Param("id") Integer id) throws DataAccessException; in das SpecialtyRepository, andernfalls wird die folgende Ausnahme ausgelöst: "java.lang.IllegalStateException: Repository doe Ich habe keine Find-One-Methode deklariert! "

package org.springframework.samples.petclinic.vet; 

import java.util.Collection; 

import org.springframework.dao.DataAccessException; 
import org.springframework.data.repository.Repository; 
import org.springframework.data.repository.query.Param; 
import org.springframework.transaction.annotation.Transactional; 

public interface SpecialtyRepository extends Repository<Specialty, Integer> { 

    @Transactional(readOnly = true) 
    Collection<Specialty> findAll() throws DataAccessException; 

    Specialty findOne(@Param("id") Integer id) throws DataAccessException; 
} 
0

Hier ist, wie ich es tat:

<select th:field="*{influenceIds}" ID="txtCategoryName" class="m-wrap large" multiple="multiple"> 
    <option th:each="influence : ${influences}" th:value="${influence.get('id')}" th:text="${influence.get('influence')}" ></option> 
</select> 

Mein DTO enthält:

private List<String> influenceIds;