Множественный тимелеар, выбранный при редактировании
Я полностью меняю этот вопрос, так как часть ответа была получена здесь с большой помощью Avnish!
Том послал меня в правильное направление, поэтому спасибо Том!
Моя проблема в том, что я не знаю, как сообщить Тимелеафу предварительно выбрать элементы объекта при его редактировании.
Позвольте мне показать вам:
![looks like this]()
Это решение работает:
<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>
Я пробовал это:
<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>
не работает. Я также пробовал это:
<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>
тоже не работает. Я попытался удалить th: field = "* {parts}" из тега опции, тот же результат.
Если я меняю th: значение на ${part}, он работает, но затем он не отправляет обратно строку идентификаторов вроде [2,4,5,6,...], но экземпляры экземпляров, такие как [Part @43b45j, Part @we43y7,...]...
UPDATE: Я просто замечаю, что это работает, если выбрана только одна часть:
<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>
Если выбрано несколько частей, это не сработает...
Ответы
Ответ 1
После обсуждения форума Thymeleaf я внедрил полный рабочий пример на https://github.com/jmiguelsamper/thymeleafexamples-selectmultiple
Я думаю, что единственная проблема с вашим окончательным кодом заключается в том, что для вызова функции conversionService вам необходимо использовать двойной синтаксис:
th:value="${{part}}"
Также важно реализовать правильные методы equals() и hashcode() в вашем классе Part, чтобы обеспечить правильное сравнение.
Надеюсь, мой пример поможет другим пользователям с подобными проблемами в будущем.
Ответ 2
Вам не нужно th:selected
при обычном использовании th:field
. Thymeleaf автоматически проверяет значения каждого <option>
в <select>
, даже если это multiple
Проблема заключается в значении. Вы выполняете итерацию parts
, но значение каждой опции part.id
. Таким образом, вы сравниваете экземпляры части с идентификатором части (насколько я могу видеть).
Однако Тимелеаф также учитывает экземпляры PropertyEditor
(он повторно использует org.springframework.web.servlet.tags.form.SelectedValueComparator
).
Это будет использоваться при сравнении объектов со значениями параметров. Он преобразует объекты в их текстовое значение (их идентификатор) и сравнивает его со значением.
<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>
Редактор свойств
Определите a PropertyEditor
для частей. PropertyEditor будет вызываться при сравнении значений и при привязке частей к форме.
@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
}
}
}
Также посмотрите ConvertingPropertyEditorAdapter
. Converter
экземпляры, зарегистрированные в conversionService
, более предпочтительны в Spring в настоящее время.
Ответ 3
<select th:field="*{groupId}" >
<option th:each="group :${grouptype}"
th:value="${{group.groupId}}"
th:text="${group.Desc}">
</option>
</select>
Пример простого выбора
Ответ 4
Это работает для меня:
У ветеринара много специальностей.
Контроллер:
@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;
}
Просмотр (с использованием 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>
Просмотр (с использованием 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>
И я должен определить Specialty findOne(@Param("id") Integer id) throws DataAccessException;
в SpecialtyRepository, в противном случае выдается следующее исключение: "java.lang.IllegalStateException: в репозитории нет объявленного метода поиска!"
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;
}
Ответ 5
Вот как я это сделал:
<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 содержит:
private List<String> influenceIds;