问题描述
我对js很新。 我正在尝试完成一个待办事项类的应用程序。 我已经能够创建,渲染和删除数组项,但是编辑时遇到了麻烦。
所有这些操作都是通过uuidv4库完成的,以为创建的每个数组项生成一个ID。
在为数组项选择了单个ID的情况下,我正在生成动态按钮,一个用于删除数组项,另一个用于编辑。
单击编辑后,我想打开一个包含所选数组项内容的模式。 进行更改后,模态内部的编辑按钮应调用编辑函数来更新更改,然后重新呈现数组。
我的问题是,单击“编辑”按钮时无法打开模式对话框。
这是用于创建必要结构的代码,但由于它们正常工作,因此不包含用于创建,呈现和删除的代码。
// Generate the DOM structure for a todo
const generateTodoDOM = function(todo) {
const todoEl = document.createElement("div");
const checkbox = document.createElement("input");
const label = document.createElement("label");
checkbox.appendChild(label);
todoEl.setAttribute("id", "myTodos");
const textEl = document.createElement("p");
const editButton = document.createElement("button");
editButton.setAttribute("id", "modal-btn");
const removeButton = document.createElement("button");
const createDate = document.createElement("p");
createDate.textContent = `Created: ${dateCreated}`;
createDate.style.color = "#956E93";
// Setup the todo text
textEl.textContent = todo.text;
todoEl.appendChild(textEl);
// Setup the remove button
removeButton.textContent = "x";
todoEl.appendChild(removeButton);
removeButton.addEventListener("click", function() {
removeTodo(todo.id);
saveTodos(todos);
renderTodos(todos, filters);
});
// TODO: Setup the edit note button
editButton.textContent = "Edit Todo";
todoEl.appendChild(editButton);
editButton.addEventListener("click", function() {
//Launch the modal
editModal(todo.id);
});
// Setup todo checkbox
checkbox.setAttribute("type", "checkbox");
checkbox.checked = todo.completed;
todoEl.appendChild(checkbox);
checkbox.addEventListener("change", function() {
toggleTodo(todo.id);
saveTodos(todos);
renderTodos(todos, filters);
});
todoEl.appendChild(createDate);
return todoEl;
};
模态的代码如下:
//Edit modal todo by id
const editModal = function(id) {
const todoIndex = todos.findIndex(function(todo) {
return todo.id === id;
});
if (todoIndex > -1) {
const modal = document.querySelector("#my-modal");
const modalBtn = document.querySelector("#modal-btn");
const editTodoContentBtn = document.querySelector("#submitEditTodo")
const closeBtn = document.querySelector(".close");
// Events
modalBtn.addEventListener("click", openModal);
closeBtn.addEventListener("click", closeModal);
editTodoContentBtn.addEventListener("click", editTodo)
window.addEventListener("click", outsideClick);
// Open
function openModal() {
modal.style.display = "block";
}
// Close
function closeModal() {
modal.style.display = "none";
}
// Close If Outside Click
function outsideClick(e) {
if (e.target == modal) {
modal.style.display = "none";
}
}
//Edit the content of the textarea
function editTodo(e) {
editTodo(id)
}
}
};
单击submitEditTodo按钮时,应触发以下编辑功能:
//Edit todo by id
const editTodo = function(id) {
const editTodoContent = document.querySelector('#editTodo')
const todoIndex = todos.findIndex(function(todo) {
return todo.id === id;
});
if (todoIndex > -1) {
editTodoContent.value = todos.text
saveTodos(todos)
renderTodos(todos, filters);
}
};
saveTodos和renderTodos与其他用于创建,渲染和删除的功能一起正常运行。
这是HTML代码:
<!-- Edit modal -->
<div id="my-modal" class="modal">
<div class="modal-content">
<div class="modal-header">
<span class="close">×</span>
<h2>Edit Todo</h2>
</div>
<div class="modal-body">
<textarea name="" class="editTextArea" id="editTodo" rows="10"></textarea>
<button class="button" id="submitEditTodo">Edit Todo</button>
</div>
<div class="modal-footer">
<!-- <h3>Modal Footer</h3> -->
</div>
</div>
<!-- End modal -->
这是模式的CSS:
/*
Edit todo modal start
*/
:root {
--modal-duration: 1s;
--modal-color: #BB8AB8;
}
.modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
height: 100%;
width: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
.modal-content {
margin: 10% auto;
width: 35%;
box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.17);
animation-name: modalopen;
animation-duration: var(--modal-duration);
}
.editTextArea{
width:100%
}
.modal-header h2,
.modal-footer h3 {
margin: 0;
}
.modal-header {
background: var(--modal-color);
padding: 15px;
color: #fff;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.modal-body {
padding: 10px 20px;
background: #fff;
}
.modal-footer {
background: var(--modal-color);
padding: 10px;
color: #fff;
text-align: center;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
.close {
color: #ccc;
float: right;
font-size: 30px;
color: #fff;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
@keyframes modalopen {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/*
Edit todo modal end
*/
谢谢
1楼
以下是一些可能需要调整以实现所需功能的指针。
当前,每次单击待办事项的编辑按钮时,都将新的侦听器添加到模式中。 这可能应该只设置一次。 或者,应该在模式关闭时删除侦听器。
您的函数editModal实际上并未打开模态。 它的作用是在#modal-btn按钮上添加一个侦听器,该监听器将在下次单击该按钮时打开模式。
您正在为外部div和“编辑”按钮设置ID,但是ID并不基于与您要创建的todo元素相关的任何内容。 因此,所有这些元素实际上都具有相同的id。 id(标识符的缩写)通常是唯一的。 对于多个元素的分组,您应该改为使用class属性。
您的函数“ editTodo”会自行调用。 无限递归。 当心重用函数名称。
话虽如此,以下代码是根据您提供的摘录执行我认为想要执行的操作的粗略方法:
// Open const openModal = function() { document.querySelector("#my-modal").style.display = "block"; } // Close const closeModal = function() { document.querySelector("#my-modal").style.display = "none"; } function initModal() { const modal = document.querySelector("#my-modal"); const closeBtn = document.querySelector(".close"); // Events closeBtn.addEventListener("click", closeModal); window.addEventListener("click", outsideClick); // Close If Outside Click function outsideClick(e) { if (e.target == modal) { modal.style.display = "none"; } } } const filters = []; // dummy variable // Generate the DOM structure for a todo var todos = [] function generateTodoDOM(todo) { todos.push(todo); const todoEl = document.createElement("div"); const checkbox = document.createElement("input"); const label = document.createElement("label"); checkbox.appendChild(label); todoEl.setAttribute("id", "my-todos-" + todo.id); const textEl = document.createElement("p"); const editButton = document.createElement("button"); editButton.setAttribute("id", "modal-btn-" + todo.id); const removeButton = document.createElement("button"); const createDate = document.createElement("p"); createDate.textContent = 'Created: ' + new Date(); createDate.style.color = "#956E93"; // Setup the todo text textEl.textContent = todo.text; todoEl.appendChild(textEl); // Setup the remove button removeButton.textContent = "x"; todoEl.appendChild(removeButton); removeButton.addEventListener("click", function() { removeTodo(todo.id); saveTodos(todos); renderTodos(todos, filters); }); // TODO: Setup the edit note button editButton.textContent = "Edit Todo"; todoEl.appendChild(editButton); editButton.addEventListener("click", function() { //Launch the modal editModal(todo.id); openModal(); }); // Setup todo checkbox checkbox.setAttribute("type", "checkbox"); checkbox.checked = todo.completed; todoEl.appendChild(checkbox); checkbox.addEventListener("change", function() { toggleTodo(todo.id); saveTodos(todos); renderTodos(todos, filters); }); todoEl.appendChild(createDate); return todoEl; }; var editFn //Edit modal todo by id const editModal = function(id) { const todoIndex = todos.findIndex(function(todo) { return todo.id === id; }); if (todoIndex > -1) { const modal = document.querySelector("#my-modal"); const editElm = document.querySelector("#editTodo"); const editTodoContentBtn = document.querySelector("#submitEditTodo") editElm.value = todos[todoIndex].text; // Events editTodoContentBtn.removeEventListener("click", editFn) //Edit the content of the textarea editFn = function(e) { editTodo(id) closeModal() } editTodoContentBtn.addEventListener("click", editFn) } }; //Edit todo by id const editTodo = function(id) { const editTodoContent = document.querySelector('#editTodo') const todoIndex = todos.findIndex(function(todo) { return todo.id === id; }); if (todoIndex > -1) { todos[todoIndex].text = editTodoContent.value; saveTodos(todos) renderTodos(todos, filters); } }; const saveTodos = function(todos) { // dummy method, we're keeping it in memory for this example } const renderTodos = function(todosToRender) { todos = []; // clear current in-memory array var todoList = document.getElementById("todo-container"); while (todoList.firstChild) { todoList.removeChild(todoList.firstChild); } for(var i = 0; i < todosToRender.length; i++) { todoList.appendChild(generateTodoDOM(todosToRender[i])); } }; initModal(); const container = document.getElementById("todo-container"); var generatedTodos = []; for(var i = 0; i < 10; i++) { var todo = { text: "Todo " + (i+1), id: "todo-" + i, completed: false}; generatedTodos.push(todo); } renderTodos(generatedTodos);
/* Edit todo modal start */ :root { --modal-duration: 1s; --modal-color: #BB8AB8; } .modal { display: none; position: fixed; z-index: 1; left: 0; top: 0; height: 100%; width: 100%; overflow: auto; background-color: rgba(0, 0, 0, 0.5); } .modal-content { margin: 10% auto; width: 35%; box-shadow: 0 5px 8px 0 rgba(0, 0, 0, 0.2), 0 7px 20px 0 rgba(0, 0, 0, 0.17); animation-name: modalopen; animation-duration: var(--modal-duration); } .editTextArea{ width:100% } .modal-header h2, .modal-footer h3 { margin: 0; } .modal-header { background: var(--modal-color); padding: 15px; color: #fff; border-top-left-radius: 5px; border-top-right-radius: 5px; } .modal-body { padding: 10px 20px; background: #fff; } .modal-footer { background: var(--modal-color); padding: 10px; color: #fff; text-align: center; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } .close { color: #ccc; float: right; font-size: 30px; color: #fff; } .close:hover, .close:focus { color: #000; text-decoration: none; cursor: pointer; } @keyframes modalopen { from { opacity: 0; } to { opacity: 1; } } /* Edit todo modal end */
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="style.css"> </head> <body> <div id="todo-container"> </div> <!-- Edit modal --> <div id="my-modal" class="modal"> <div class="modal-content"> <div class="modal-header"> <span class="close">×</span> <h2>Edit Todo</h2> </div> <div class="modal-body"> <textarea name="" class="editTextArea" id="editTodo" rows="10"></textarea> <button class="button" id="submitEditTodo">Edit Todo</button> </div> <div class="modal-footer"> <!-- <h3>Modal Footer</h3> --> </div> </div> </div> <!-- End modal --> </body> </html>