我完全改变了这个问题,因为其中的一部分在Avnish的帮助下得到了here的回答! 汤姆把我送到正确的方向,谢谢汤姆!
我的问题是我不知道如何告诉Thymeleaf在编辑时预先选择对象元素。
让我告诉你:
此解决方案有效:
<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:value
更改为${part}
它可以正常工作,但它不会发回像[2,4,5,6,...]这样的ID字符串,但是{{1}例如[Part @ 43b45j,Part @ we43y7,...] ......
更新:我刚注意到只有选择了一个部分才有效:
Part
如果选择了多个部分,则无效...
答案 0 :(得分:13)
在Thymeleaf论坛上讨论后,我实施了一个完整的工作示例 https://github.com/jmiguelsamper/thymeleafexamples-selectmultiple
我认为最终代码的唯一问题是你必须使用双括号语法来调用conversionService:
th:value="${{part}}"
在Part类中实现正确的equals()和hashcode()方法也很重要,以确保正确比较。
我希望我的示例可以帮助其他用户解决类似问题。
答案 1 :(得分:7)
正常使用th:selected
时,您不需要th:field
。 Thymeleaf将自动检查<option>
中每个<select>
的值,即使它是multiple
问题在于价值。您正在迭代parts
,但每个选项的值均为part.id
。因此,您将部件的实例与部件的ID进行比较(据我所见)。
然而,Thymeleaf还会考虑PropertyEditor
的实例(它重用org.springframework.web.servlet.tags.form.SelectedValueComparator
)。
将对象与选项的值进行比较时将使用此选项。它会将对象转换为文本值(它们的id)并将其与值进行比较。
<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>
属性编辑器
为部件定义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中更受欢迎。
答案 2 :(得分:1)
这对我有用:
兽医有许多专业。
控制器:
@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:已选择):
<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:字段):
<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>
我必须在SpecialtyRepository中定义Specialty findOne(@Param("id") Integer id) throws DataAccessException;
,否则抛出以下异常:&#34; java.lang.IllegalStateException:存储库没有声明find-one-method!& #34;
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;
}
答案 3 :(得分:0)
我是这样做的:
<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>
我的DTO包含:
private List<String> influenceIds;
答案 4 :(得分:0)
<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>
答案 5 :(得分:-1)
<select th:field="*{groupId}" >
<option th:each="group :${grouptype}"
th:value="${{group.groupId}}"
th:text="${group.Desc}">
</option>
</select>
简单选择示例