Spring Boot+Thymeleaf中JS控制textarea必填属性失效问题排查
问题排查与解决方案
核心问题分析
你的代码存在4个关键问题,导致动态设置textarea必填属性的功能失效:
重复ID导致DOM元素获取错误
由于Thymeleaf通过th:each循环生成多行提问,所有下拉框的默认选项和textarea都使用了相同的固定ID(noSelectOption2、commentAreaForQuestion2)。document.getElementById()只能返回第一个匹配的元素,后续行的元素完全无法被JS正确定位。事件绑定错误
下拉框选项变更的正确触发事件是onchange,你误用了onselect(该事件用于文本输入框的文本选中操作)。逻辑判断颠倒
需求是「选择非默认选项时textarea必填,选默认选项时移除必填」,但你的JS逻辑正好相反:当默认选项值为空时设置required=true,完全不符合需求。HTML标签语法错误
select标签被写成了自闭合形式<select .../>,后续又添加了</select>,导致浏览器解析HTML结构异常。
修改后的代码实现
Thymeleaf模板代码
重点为循环生成的元素添加唯一ID,修正事件绑定和标签语法:
<div class="container-fluid bg-light"> <div class="form-group table" th:if="${answeredQuestionnaire.answers.size()==0}"> <table> <thead style="background-color: dimgrey; color: white"> <tr class="d-flex"> <th scope="col" class="col-4 text-center">[[#{questionnaire.question}]]</th> <th scope="col" class="col-4 text-center">[[#{questionnaire.answer}]]</th> <th scope="col" class="col-4 text-center" >[[#{questionnaire.comment}]]<font color="red">*</font></th> </tr> </thead> <tbody th:field="*{questionnaire}"> <tr th:each="question,iStat : ${answeredQuestionnaire.questionnaire.getQuestions()}" class="d-flex"> <td class="col-4" th:inline="text"> <input type="hidden" th:value="${question.id}" th:field="*{questionnaire.questions[__${iStat.index}__].id}" th:text="${question.questionNumber + 1}+') '+#{'question'+${question.questionNumber}}"/> </td> <td class="col-4 text-center"> <!-- 修正select标签闭合,使用onchange事件并传递当前元素和索引 --> <select th:field="*{questionnaire.questions[__${iStat.index}__].possibleAnswers[0].id}" class="form-control" onchange="toggleCommentRequired(this, [[${iStat.index}]])"> <!-- 生成唯一ID --> <option value="" default th:id="'noSelectOption_' + ${iStat.index}" >[[#{pleaseSelect}]]</option> <option th:each="possibleAnswer, paStat : ${question.getPossibleAnswers()}" th:value="${possibleAnswer.id}" th:text="#{'question'+${question.questionNumber}+'.pa'+${paStat.index}}"> </option> </select> </td> <td class="col-4"> <!-- 生成唯一ID --> <textarea th:id="'commentArea_' + ${iStat.index}" th:value="${question.comment}" placeholder="comment" class="form-control" th:field="*{questionnaire.questions[__${iStat.index}__].comment}" th:placeholder="#{comment}" rows="3" ></textarea> </td> </tr> </tbody> </table> </div> </div>
actions.js代码
修正逻辑,通过传递的参数定位对应元素:
function toggleCommentRequired(selectElement, index) { const selectedValue = selectElement.value; const commentArea = document.getElementById(`commentArea_${index}`); if (selectedValue !== "") { // 选中非默认选项,设置必填属性 commentArea.setAttribute("required", "required"); } else { // 选中默认选项,移除必填属性 commentArea.removeAttribute("required"); } }
验证建议
- 打开浏览器开发者工具的Console面板,在函数内添加
console.log(selectedValue, commentArea),确认是否能正确获取选中值和对应textarea元素。 - 手动切换下拉选项后,在Console中执行
commentArea.hasAttribute('required'),验证属性是否按预期设置。
内容的提问来源于stack exchange,提问作者Syed Iftekharuddin
相关产品推荐
相关产品推荐

