thymeleaf multiple selected on edit

。_饼干妹妹 提交于 2019-12-17 18:37:31

问题


I am totally changing this question, as part of it was answered here with great help of Avnish! Tom sent me to the right direction so thank you Tom!

My problem is that I do not know how to tell Thymeleaf to preselect object elements when editing it.

Let me show you:

This solution works:

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

I have tried this:

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

did not work. I also tried this:

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

did not work either. I have tried removing th:field="*{parts}" from the option tag, same result..

If I change th:value to ${part} it works, but then it does not send back string of ids like [2,4,5,6,...], but Part instances like [Part@43b45j, Part@we43y7,...]...

UPDATE: I just noticed that this works if only one part is selected:

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

If multiple parts are selected, it does not work...


回答1:


After discussion on the Thymeleaf forum, I implemented a full working example at https://github.com/jmiguelsamper/thymeleafexamples-selectmultiple

I think that the only problem with your final code is that you have to use double bracket syntax to invoke the conversionService:

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

It is also important to implement proper equals() and hashcode() methods in your Part class to assure proper comparison.

I hope my example helps other users with similar problems in the future.




回答2:


You don't need th:selected when using th:field normally. Thymeleaf will automatically check the values of each <option> in the <select>, even if it is multiple

The problem lies in the value. You are iterating over parts, but the value of each option is part.id. Thus you are comparing instances of part to the id of part (as far as I can see).

However, Thymeleaf also takes into account instances of PropertyEditor (it reuses org.springframework.web.servlet.tags.form.SelectedValueComparator).

This will be used when comparing the objects to the values of the options. It will convert the objects to their text value (their id) and compare this to the value.

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

Property Editor

Define a PropertyEditor for the parts. The PropertyEditor will be called when comparing the values, and when binding the parts back to the form.

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

Also take a look at ConvertingPropertyEditorAdapter. Converter instances that are registered in the conversionService are more preferred in Spring nowadays.




回答3:


This works for me:

A vet has many specialties.

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

View (using th:selected):

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

View (using th:field):

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

And I have to define Specialty findOne(@Param("id") Integer id) throws DataAccessException; in the SpecialtyRepository, otherwise the following exception is thrown : "java.lang.IllegalStateException: Repository doesn't have a find-one-method declared!"

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



回答4:


Here's how I did it:

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

My DTO contains:

private List<String> influenceIds;



回答5:


<select id="produtos" name="selectedItens" style="width: 100%;" multiple="multiple" required="">
                <option th:value="${p.id}" th:text="${p}" th:each="p : ${slideShowForm.itens}" th:selected="${#lists.contains(slideShowForm.selectedItens,p)}"></option>
            </select>



回答6:


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

    </option>
</select>

Simple select example



来源:https://stackoverflow.com/questions/22246759/thymeleaf-multiple-selected-on-edit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!