为type=date的input添加required属性失效问题排查
表单必填验证异常问题分析与解决
问题描述
我制作了一个包含4个输入项的表单,为每个输入项都添加了required属性,要求用户必须填写完成才能提交表单。但发现未填写type=date类型的输入框时,不会触发“此字段为必填项”的提示;将date输入框移至radio输入项之前后,该属性正常生效。请问这是什么原因?
HTML代码
<form action="" id="task-form"> <div class="buttons-container"> <button class="cancel">cancel</button> <button class="add-btn-inside-box" id="task-add-btn">Add</button> </div> <div class="title-area"> <h2 class="title">Title</h2> <input type="text" placeholder="add a title..." id="task-title" required> </div> <div class="description-area"> <h2 class="description">Description</h2> <textarea placeholder="add a title..." id="task-description" required></textarea> </div> <div class="tags-area"> <h2 class="tags">Tags</h2> <input type="radio" id="work" name="tags" value="work" required> <p class="work-tag" style="display: inline;">Work</p> <input type="radio" id="study" name="tags" value="study" required> <p class="study-tag" style="display: inline;" >Study</p> <input type="radio" id="entertaiment" name="tags" value="Entertainment" required> <p class="entertaiment-tag" style="display: inline;">Entertainment</p> <input type="radio" id="family" name="tags" value="family" required> <p class="family-tag" style="display: inline;">Family</p> </div> <div class="deadline"> <h2 for="date-task">Deadline</h2> <input type="date" id="date-task" required/> </div> </form>
JS代码
const categoriesBtn = document.getElementById("categories-btn") const allCategoriesEl = document.querySelector(".categories-options") const plusBtn = document.getElementById("plus-btn") const formEl = document.getElementById("task-form") const taskContainer = document.querySelector(".task-box") const taskCancelBtn = document.querySelector(".cancel") const taskAddBtn = document.getElementById("task-add-btn") const taskTitle = document.getElementById("task-title") const taskDate = document.getElementById("date-task") const taskDescription = document.getElementById("task-description") const allTasksLocalStorage = bringTasksLocalStorage() // show/hide the categories on the menu categoriesBtn.addEventListener("click", () => allCategoriesEl.classList.toggle("categories-options-none")) // tasks box functionality plusBtn.addEventListener("click", function showTaskBox() { taskContainer.classList.add("task-box-active") }) taskCancelBtn.addEventListener("click", () => taskContainer.classList.remove("task-box-active")); //main tasks box functionality: taskAddBtn.addEventListener("click", (event) => { if(formEl.checkValidity() ){ event.preventDefault() } const taskTags = document.querySelector('input[name="tags"]:checked') const newTask = { Title: taskTitle.value, Description: taskDescription.value, Tag: taskTags.value, Date: taskDate.value }
原因分析
这是因为HTML5表单的原生验证是按照元素在DOM中的顺序依次进行的。当表单提交时,浏览器会从第一个带required属性的元素开始检查,一旦发现某个元素未通过验证(比如你的radio组没有选中任何选项),就会立即终止后续验证流程,只提示当前未通过的元素。
在你的原始代码中,radio组位于date输入框之前,当用户未选择任何radio选项时,浏览器会先检测到radio组的required验证失败,直接弹出对应提示,不会继续检查后面的date输入框,所以你看不到date的必填提示。而把date移到radio组前面后,浏览器会优先检查date输入框,未填写时就会先触发它的必填提示。
另外补充一个细节:同一name的radio组属于一个整体,只需要给组内任意一个radio添加required属性即可,不需要每个都加,这样写法更规范。
解决方案
有两种常见的解决方式:
- 调整DOM顺序:保留你已经尝试的方法,将date输入框移至radio组之前,让浏览器先验证date字段。
- 手动触发全表单验证:修改提交按钮的事件逻辑,先阻止默认提交,再调用
formEl.reportValidity()方法,该方法会触发所有字段的验证并显示对应提示,不会停在第一个错误。修改后的JS代码如下:
taskAddBtn.addEventListener("click", (event) => { event.preventDefault(); // 先阻止默认提交行为 if(formEl.checkValidity()){ // 验证通过后的业务逻辑 const taskTags = document.querySelector('input[name="tags"]:checked') const newTask = { Title: taskTitle.value, Description: taskDescription.value, Tag: taskTags.value, Date: taskDate.value } // 后续的保存、渲染等逻辑... } else { formEl.reportValidity(); // 触发所有字段的验证提示 } })
内容的提问来源于stack exchange,提问作者Amir Noyman
相关产品推荐
相关产品推荐

