You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 03:54:57