Thymeleaf中th:each内th:field语法错误引发请求属性异常
错误根源
你遇到的IllegalStateException是因为Thymeleaf的th:field属性必须配合表单对象绑定(th:object)使用。当你直接写th:field="${messageContent.type}"时,Thymeleaf会默认去请求属性中寻找名为messageContent的顶级Bean,但你的messageContent只是th:each循环里的局部变量,并非直接存放在Model中的独立属性,所以找不到目标对象导致报错。
你尝试的th:field="${messageContentList[__${iStat.index}__].type}"也无效,因为同样没有绑定到一个表单对象上,th:field的表达式需要基于th:object指定的根对象来解析。
解决方法
方法一:绑定表单对象(推荐)
假设你的DisplayMessage类中已经包含List<MessageContent> messageContentList属性(如果没有,需要先添加该属性及对应的getter/setter),修改代码如下:
控制器代码无需修改(已将
displayMessage和messageContentList加入Model)。修改HTML页面,添加表单标签并绑定
displayMessage为表单对象:
<html> <head></head> <body> <form th:object="${displayMessage}"> <!-- 添加表单对象绑定 --> <div class="col-12"> <label class="form-label"> Name of Message </label> <input type="text" class="form-control" placeholder="Enter Name Of Message" required="required" th:field="*{name}" /> <!-- 这里也可改用th:field简化绑定 --> </div> <hr /> <div th:each="messageContent, iStat : ${displayMessage.messageContentList}"> <!-- 从表单对象中取列表数据 --> <h6 align="center" th:text="'Section '+${iStat.count}"></h6> <div class="form-group"> <label class="form-label"> Select the content type </label> <select class="form-control" th:onchange="ShowHideTextMediaDiv();" th:field="*{messageContentList[__${iStat.index}__].type}"> <!-- 基于表单对象的表达式绑定 --> <option th:value="Text">Text</option> <option th:value="Image">Image</option> <option th:value="Video">Video</option> </select> <br /> </div> </div> </form> </body> </html>
方法二:不使用th:field,手动绑定值和名称
如果不想使用表单对象绑定,可以放弃th:field,改用th:value和手动设置name属性,让Spring能正确接收表单提交的列表数据:
修改HTML中的select部分:
<select name="messageContentList[${iStat.index}].type" id="messageContent_${iStat.index}" class="form-control" th:onchange="ShowHideTextMediaDiv();" th:value="${messageContent.type}"> <option th:value="Text">Text</option> <option th:value="Image">Image</option> <option th:value="Video">Video</option> </select>
注意:给每个select设置唯一的id(比如加上索引)避免DOM元素id重复;name属性的messageContentList[索引].type格式是Spring能识别的列表参数格式,提交时会自动封装到messageContentList中。
内容的提问来源于stack exchange,提问作者Anuja

