即使与问题无关,你也可以告诉我代码是否有问题。
首先,我采用了添加表格行和通过模态添加输入标签的方法。参考如何用thymeleaf绑定对象列表?实现。 但绑定失败,
optionRequests
变为空。
我错过了什么?我不知道问题是什么。
<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>
function addOptionRow() {
const table = document.getElementById('optionTable');
const newRow = table.insertRow();
const optionName = newRow.insertCell(0);
const addValue = newRow.insertCell(1);
const method = newRow.insertCell(2);
const material = newRow.insertCell(3);
const removeButton = newRow.insertCell(4);
var idx = $('#optionTable tr').length - 2;
optionNameText = $('#optionName').val();
addValueText = $('#addValue').val();
methodText = $('#method').val();
materialText = $('#material').val();
optionName.innerText = optionNameText;
addValue.innerText = addValueText;
method.innerText = methodText;
material.innerText = materialText;
removeButton.innerHTML = "<button class='btn btn-danger btn-sm' onclick='removeRow(this)'>X</button>"
$("#example-form").append($("<input type='hidden' th:field='${example.optionRequests[" + idx + "].optionName}' th:name='${example.optionRequests[" + idx + "]}' th:value='" + optionNameText + "'>"));
$("#example-form").append($("<input type='hidden' th:field='${example.optionRequests[" + idx + "].addValue}' th:name='${example.optionRequests[" + idx + "]}' th:value='" + addValueText + "'>"));
$("#example-form").append($("<input type='hidden' th:field='${example.optionRequests[" + idx + "].method}' th:name='${example.optionRequests[" + idx + "]}' th:value='" + methodText + "'>"));
$("#example-form").append($("<input type='hidden' th:field='${example.optionRequests[" + idx + "].material}' th:name='${example.optionRequests[" + idx + "]}' th:value='" + materialText + "'>"));
$('#optionName').val("");
$('#addValue').val("");
$('#method').val("");
$('#material').val("");
$('#optionModal').modal('hide');
}
</script>
DTO 定义如下。
public record FormRequest(
String title,
List<OptionRequest> optionRequests,
MultipartFile imgFile
) {}
public record OptionRequest(
String optionName,
Integer addValue,
String method,
String material
) {
}
控制器实现如下。
@GetMapping("/example")
public String exampleGet(Model model) {
model.addAttribute("example", new FormResponse(null, List.of(), null)); //Same field as in FormRequest
return "form";
}
@PostMapping("/example")
public String examplePost(
@ModelAttribute("example") FormRequest formRequest,
Model model
) {}
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>
修改如下解决了。