如何通过Bootstrap模态框表单传递数据更新表格行(Spring+Thymeleaf)
解决Bootstrap模态框中Thymeleaf表达式
countryToUpdate.id为null的问题 问题根源
你碰到的EL1007E: Property or field 'id' cannot be found on null错误,本质是两个核心问题:
- 页面首次加载时,
findAll方法未给Model添加countryToUpdate属性,Thymeleaf渲染表单th:action时,${countryToUpdate}为null,自然找不到id属性。 - 点击编辑按钮时,
findById用了@ResponseBody返回JSON,但这是AJAX请求,不会触发页面重新渲染,Model里的countryToUpdate根本不会更新,模态框仍使用初始的null值。
解决方案
方案一:非AJAX页面跳转方式
这种方式无需编写JS,通过页面跳转传递countryToUpdate属性,触发模态框显示。
1. 修改Controller
去掉findById的@ResponseBody,改为返回页面,同时添加模态框显示标记:
@GetMapping("countries/findById/{id}") public String findById(@PathVariable int id, Model model) { Country country = countryService.findById(id).get(); model.addAttribute("countryToUpdate", country); // 标记需要显示模态框 model.addAttribute("showEditModal", true); // 重新查询国家列表,保证页面数据完整 List<Country> listOfCountries = countryService.findAll(); model.addAttribute("countries", listOfCountries); return "country"; }
2. 修改页面代码
- 编辑按钮去掉
data-toggle和data-target,保留跳转链接:
<a th:href="@{/countries/findById/{id} (id=${country.id})}" class="btn btn-primary editModalBtn">Edit</a>
- 添加页面加载时自动显示模态框的JS:
<script th:if="${showEditModal}"> $(document).ready(function() { $('#editModal').modal('show'); }); </script>
- 表单绑定
countryToUpdate属性,输入框用th:field自动填充:
<form th:action="@{/countries/update/{id} (id =${countryToUpdate.id})}" method="post" th:object="${countryToUpdate}"> <div class="form-group"> <label for="descriptionEdit" class="col-form-label">Description</label> <input type="text" class="form-control" id="descriptionEdit" name="description" th:field="*{description}"> </div> <div class="form-group"> <label for="capitalEdit" class="col-form-label">Capital</label> <input type="text" class="form-control" id="capitalEdit" name="capital" th:field="*{capital}"> </div> <!-- 其余输入框同理添加th:field="*{code}"、th:field="*{continent}"等 --> </form>
方案二:AJAX异步交互方式
这种方式保留AJAX请求,用JS手动填充表单并设置action,避免初始渲染时的null问题。
1. 修改Controller
保留@ResponseBody,无需往Model加countryToUpdate:
@GetMapping("countries/findById/{id}") @ResponseBody public Country findById(@PathVariable int id) { return countryService.findById(id).get(); }
同时在findAll方法里添加空的countryToUpdate,避免Thymeleaf渲染报错:
@GetMapping("countries") public String findAll(Model model){ List<Country> listOfCountries = countryService.findAll(); model.addAttribute("countries", listOfCountries); // 添加空对象,防止Thymeleaf初始渲染报错 model.addAttribute("countryToUpdate", new Country()); return "country"; }
2. 修改页面代码
- 编辑按钮改为按钮,绑定国家ID:
<button class="btn btn-primary editModalBtn" data-id="${country.id}">Edit</button>
- 表单去掉
th:action,用JS动态设置:
<form id="editForm" method="post" th:object="${countryToUpdate}"> <!-- 输入框保持原有结构,无需th:field --> <div class="form-group"> <label for="descriptionEdit" class="col-form-label">Description</label> <input type="text" class="form-control" id="descriptionEdit" name="description"> </div> <!-- 其余输入框不变 --> </form>
- 添加JS处理点击事件:
<script> $(document).on('click', '.editModalBtn', function() { const countryId = $(this).data('id'); // AJAX获取国家数据 $.get('/countries/findById/' + countryId, function(country) { // 填充表单字段 $('#descriptionEdit').val(country.description); $('#capitalEdit').val(country.capital); $('#codeEdit').val(country.code); $('#continentEdit').val(country.continent); $('#nationalityEdit').val(country.nationality); // 设置表单提交地址 $('#editForm').attr('action', '/countries/update/' + country.id); // 显示模态框 $('#editModal').modal('show'); }); }); </script>
总结
- 方案一适合简单场景,无需JS,依赖页面跳转传递数据。
- 方案二更适合交互流畅的单页场景,用AJAX异步处理数据。
内容的提问来源于stack exchange,提问作者Majid
相关产品推荐
相关产品推荐

