Как редактировать элемент массива с помощью javascript

Я довольно новичок в js. Я пытаюсь завершить приложение типа todo. Мне удалось создать, отобразить и удалить элемент массива, но у меня возникли проблемы с редактированием.

Все эти операции выполняются с помощью библиотеки uuidv4 для генерации идентификатора для каждого созданного элемента массива.

С индивидуальным идентификатором, выбранным для элемента массива, я создаю динамические кнопки, одну для удаления элемента массива, другую для редактирования.

После нажатия кнопки «Изменить» я хочу открыть модальное окно, содержащее содержимое выбранного элемента массива. После внесения изменений кнопка редактирования внутри модального окна должна вызвать функцию редактирования, чтобы обновить изменения, а затем повторно отобразить массив.

Моя проблема в том, что я не могу открыть модальное диалоговое окно при нажатии кнопки редактирования.

Это код для создания необходимой структуры, код для создания, рендеринга и удаления не включен, так как они работают правильно.

// 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">&times;</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
*/

Спасибо

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
2
223
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ниже приведены несколько указателей на то, где вам могут понадобиться корректировки для достижения того, что вы хотите.

  1. В настоящее время вы добавляете новых слушателей в модальное окно каждый раз, когда нажимаете кнопку редактирования задачи. Вероятно, это должно быть установлено только один раз. В качестве альтернативы вы должны удалить слушателей, когда модальное окно закрыто.

  2. Ваша функция editModal на самом деле не открывает модальное окно. Что он делает, так это добавляет прослушиватель к кнопке #modal-btn, которая затем откроет модальное окно при следующем нажатии кнопки.

  3. Вы устанавливаете идентификаторы как для внешнего div, так и для кнопки редактирования, но идентификаторы не основаны ни на чем, связанном с создаваемым вами элементом todo. Таким образом, все эти элементы имеют один и тот же идентификатор. Идентификатор (сокращение от идентификатора) обычно должен быть уникальным. Вместо этого для группировки нескольких элементов следует использовать атрибут класса.

  4. Ваша функция "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">&times;</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>

Другие вопросы по теме