JavaScript看板应用中点击编辑后date input无法唤起日历的问题
看板应用日期输入框无法唤起日历选择器问题
我开发了一个Kanban(看板)应用,其余功能均正常,但点击Edit(编辑)按钮后,date input无法像常规情况那样唤起日历选择器。我仅移除了该输入框的hide类,未进行其他操作;手动编辑日期时,数据能正常更新。
相关代码如下:
import Kanban from "./kanban.js"; const todo = document.querySelector(".cards.todo") const pending = document.querySelector(".cards.pending") const completed= document.querySelector(".cards.completed") const cards = document.getElementsByClassName("card") console.log(cards) const taskbox = [todo, pending, completed] function addTaskCard(task, index) { taskbox[index].innerHTML += ` <form class="card" draggable="true" data-id="${task.taskId}"> <input type="text" name="task" autocomplete="off" value="${task.content}"/> <span class="date">${task.date}</span> <input type="date" class="deadline-input hide" name="date"/> <div> <span class="task-id"> #${task.taskId} </span> <span> <button class="edit" data-id="${task.taskId}">Edit</button> <button class="update hide" data-id="${task.taskId}" data-column="${index}">Update</button> <button class="delete" data-id="${task.taskId}">Delete</button> </span> </div> </form> ` } Kanban.getAllTasks().forEach((tasks, index) => { tasks.forEach(task => { addTaskCard(task, index) }) }) const addForm = document.querySelectorAll(".add") addForm.forEach(form => { form.addEventListener("submit", event => { event.preventDefault() console.log(form.date) if(form.task.value.trim()) { const task = Kanban.insertTask(form.submit.dataset.id, form.task.value.trim(), form.date.value) addTaskCard(task, form.submit.dataset.id) form.reset() } }) }) taskbox.forEach(column => { column.addEventListener("click", event => { event.preventDefault() const card = event.target.closest(".card") if (!card) return const dateDisplay = card.querySelector('span'); const formInput = card.querySelector('input[name="task"]') const dateInput = event.target.closest(".card").querySelector('input[name="date"]') if(event.target.classList.contains("edit")) { formInput.removeAttribute("disabled") dateInput.classList.remove("hide"); dateInput.value = dateDisplay.textContent.trim(); dateDisplay.classList.add("hide") event.target.classList.add("hide") event.target.nextElementSibling.classList.remove("hide") } if(event.target.classList.contains("update")) { formInput.setAttribute("disabled", "disabled") event.target.classList.add("hide") event.target.previousElementSibling.classList.remove("hide") dateInput.classList.add("hide") dateDisplay.classList.remove("hide") dateDisplay.textContent = dateInput.value const taskId = event.target.dataset.id const columnId = event.target.dataset.column const content =formInput.value const date = dateInput.value Kanban.updateTask(taskId, {columnId, date, content}) } if(event.target.classList.contains("delete")) { formInput.parentElement.remove() Kanban.deleteTask(event.target.dataset.id) } }) column.addEventListener("dragstart", event => { if(event.target.classList.contains("card")) { event.target.classList.add("dragging") } }) column.addEventListener("dragover", event => { const card = document.querySelector(".dragging") console.log(card) column.appendChild(card) }) column.addEventListener("dragend", event => { if(event.target.classList.contains("card")) { event.target.classList.remove("dragging") console.log(event.target.task.value) Kanban.updateTask(event.target.dataset.id, {columnId: event.target.parentElement.dataset.id, content: event.target.task.value}) } }) }) function updateTaskCardStyle() { const now = new Date(); for(const card of cards) { console.log("YES") const deadlineInput = card.querySelector('.date') console.log(deadlineInput) const deadline = new Date(deadlineInput.textContent) if (deadline < now) { card.classList.add('deadline-passed') } } } window.addEventListener('load', updateTaskCardStyle)
我预期点击date input后会弹出日历,但实际并未出现。
问题原因
问题出在column的点击事件处理里,你一开始就调用了event.preventDefault(),这个方法会阻止所有点击行为的默认动作——包括date input被点击时唤起日历选择器的原生行为。虽然手动输入日期能正常更新,但点击唤起日历的动作被全局阻止了。
解决方案
调整事件阻止逻辑,只在点击按钮(Edit/Update/Delete)时调用event.preventDefault(),避免影响date input的原生行为。修改后的点击事件代码如下:
taskbox.forEach(column => { column.addEventListener("click", event => { const card = event.target.closest(".card") if (!card) return // 仅在点击按钮时阻止默认表单提交行为 if (event.target.tagName === 'BUTTON') { event.preventDefault(); } const dateDisplay = card.querySelector('.date'); const formInput = card.querySelector('input[name="task"]') const dateInput = card.querySelector('input[name="date"]') if(event.target.classList.contains("edit")) { formInput.removeAttribute("disabled") dateInput.classList.remove("hide"); dateInput.value = dateDisplay.textContent.trim(); dateDisplay.classList.add("hide") event.target.classList.add("hide") event.target.nextElementSibling.classList.remove("hide") } // 后续Update/Delete逻辑保持不变 if(event.target.classList.contains("update")) { formInput.setAttribute("disabled", "disabled") event.target.classList.add("hide") event.target.previousElementSibling.classList.remove("hide") dateInput.classList.add("hide") dateDisplay.classList.remove("hide") dateDisplay.textContent = dateInput.value const taskId = event.target.dataset.id const columnId = event.target.dataset.column const content =formInput.value const date = dateInput.value Kanban.updateTask(taskId, {columnId, date, content}) } if(event.target.classList.contains("delete")) { formInput.parentElement.remove() Kanban.deleteTask(event.target.dataset.id) } }) // 拖拽相关逻辑保持不变 column.addEventListener("dragstart", event => { if(event.target.classList.contains("card")) { event.target.classList.add("dragging") } }) column.addEventListener("dragover", event => { const card = document.querySelector(".dragging") console.log(card) column.appendChild(card) }) column.addEventListener("dragend", event => { if(event.target.classList.contains("card")) { event.target.classList.remove("dragging") console.log(event.target.task.value) Kanban.updateTask(event.target.dataset.id, {columnId: event.target.parentElement.dataset.id, content: event.target.task.value}) } }) })
说明
因为卡片是form元素,点击按钮默认会触发表单提交,所以我们只需要在点击按钮时阻止这个默认行为即可;而点击date input时,不阻止其原生行为,就能正常唤起日历选择器了。
内容的提问来源于stack exchange,提问作者Tooba Jamal
相关产品推荐
相关产品推荐

