Thymeleaf绑定对象列表失败,optionRequests接收为null求助
问题描述
即使与当前问题无关,也请指出代码中存在的错误。
我参考一篇关于Thymeleaf绑定对象列表的文章,用模态框添加表格行和input标签实现功能,但绑定失败,optionRequests始终为null。我遗漏了什么?不清楚问题出在哪里。
HTML & JavaScript
<form id="example-form" enctype="multipart/form-data"> <input type="text" class="form-control" id="title" name="title" required> <input type="file" accept="image/*" class="form-control" id="imgFile" name="imgFile"> <input type="button" value="Add Option" class="btn btn-primary btn-sm" data-bs-toggle="modal" data-bs-target="#optionModal"> <!-- 此处有多余的</div>标签,需移除 --> <div class="modal fade" id="optionModal" tabindex="-1" aria-labelledby="optionModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title fs-5" id="optionModalLabel">option</h1> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> <input type="text" class="form-control" id="optionName"> <input type="text" class="form-control" id="addValue"> <input type="text" class="form-control" id="method"> <input type="text" class="form-control" id="material"> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button> <button type="button" class="btn btn-primary" onclick="addOptionRow()">Add</button> </div> </div> </div> <table class="table table-bordered" id="optionTable"> <thead> <tr> <th>Name</th> <th>AddValue</th> <th>Method</th> <th>Material</th> <th></th> </tr> </thead> <tbody> </tbody> </table> <!-- 缺少表单提交按钮 --> </form>
<script> // 建议维护独立计数器,避免删除行后索引混乱 let optionIndex = 0; function addOptionRow() { const table = document.getElementById('optionTable'); const newRow = table.insertRow(); const optionNameCell = newRow.insertCell(0); const addValueCell = newRow.insertCell(1); const methodCell = newRow.insertCell(2); const materialCell = newRow.insertCell(3); const removeButtonCell = newRow.insertCell(4); const optionNameText = $('#optionName').val(); const addValueText = $('#addValue').val(); const methodText = $('#method').val(); const materialText = $('#material').val(); optionNameCell.innerText = optionNameText; addValueCell.innerText = addValueText; methodCell.innerText = methodText; materialCell.innerText = materialText; removeButtonCell.innerHTML = "<button class='btn btn-danger btn-sm' onclick='removeRow(this)'>X</button>" // 修复:直接生成符合Spring绑定规则的name属性,Thymeleaf属性无法在客户端JS中解析 $("#example-form").append($(`<input type='hidden' name='optionRequests[${optionIndex}].optionName' value='${optionNameText}'>`)); $("#example-form").append($(`<input type='hidden' name='optionRequests[${optionIndex}].addValue' value='${addValueText}'>`)); $("#example-form").append($(`<input type='hidden' name='optionRequests[${optionIndex}].method' value='${methodText}'>`)); $("#example-form").append($(`<input type='hidden' name='optionRequests[${optionIndex}].material' value='${materialText}'>`)); optionIndex++; $('#optionName').val(""); $('#addValue').val(""); $('#method').val(""); $('#material').val(""); $('#optionModal').modal('hide'); } function removeRow(btn) { btn.closest('tr').remove(); } </script>
DTO定义
FormRequest
public record FormRequest( String title, List<OptionRequest> optionRequests, MultipartFile imgFile ) {}
OptionRequest
public record OptionRequest( String optionName, Integer addValue, String method, String material ) { }
Controller实现
@GetMapping("/example") public String exampleGet(Model model) { // 修复:统一使用FormRequest作为模型对象,避免类型不匹配 model.addAttribute("example", new FormRequest(null, new ArrayList<>(), null)); return "form"; } @PostMapping("/example") public String examplePost( @ModelAttribute("example") FormRequest formRequest, Model model ) { // 处理提交逻辑 return "form"; }
Thymeleaf解耦逻辑
<?xml version="1.0"?> <thlogic> ... <attr sel="#example-form" th:object="${example}" th:action="/example" th:method="post"> <attr sel="#title" th:value="*{title} ?: _"/> ... </thlogic>
核心问题与修复总结
- Thymeleaf属性无法在客户端JS中生效:你在JS里动态添加的
th:field、th:name是服务端渲染属性,客户端执行JS时不会被解析,导致input没有正确的name属性,Spring无法绑定列表。需直接生成符合规则的name:optionRequests[index].propertyName。 - 索引计算逻辑缺陷:依赖表格行数计算索引,删除行后会出现索引断层,需用独立计数器维护连续索引。
- HTML结构错误:存在多余的
</div>标签,会破坏DOM结构,需移除;缺少表单提交按钮,无法触发提交。 - 模型对象类型不匹配:Get请求用
FormResponse,Post请求接收FormRequest,虽字段相同但易引发绑定问题,需统一类型。 - 类型转换风险:
addValue对应Integer类型,前端input是text类型,需添加前端数字校验,避免提交非数字导致绑定失败。
内容的提问来源于stack exchange,提问作者jadekim
相关产品推荐
相关产品推荐

