Проблема с удалением элемента из массива
Пишу ToDo. Столкнулся с проблемой: при удалении задачи из массива вылезает ошибка Cannot set property 'Вставьте слово' of undefined. Ошибка вылезает только если создано 2 и более задач. Проблема в функции deleteTask(). Пытался удалять с помощью delete - та же история. Что нужно сделать, чтобы удалялся один элемент массива и не вылезала эта ошибка?
Вот код:
(function() {
// ToDo
const tasks = [];
(function() {
// UI
const addTask = document.getElementById('addNewTask'),
addTaskBut = addTask.elements.addTaskBut,
taskContent = addTask.elements.taskText;
// Events
window.onload = () => {
loadTasks();
};
addTaskBut.addEventListener('click', createTask);
// Functions
function createTask(e) {
e.stopPropagation();
e.preventDefault();
if (!taskContent.value) {
alert('Нельзя создать пустую задачу');
return;
}
const task = {
id: Math.random(),
content: taskContent.value
};
tasks.push(task);
loadTasks();
console.log(tasks);
}
function loadTasks() {
const fragment = document.createDocumentFragment(),
fragmentAppend = document.querySelector('.tasks');
fragmentAppend.innerHTML = '';
tasks.forEach(task => {
let item = document.createElement('div'),
content = document.createElement('div'),
deleteBtn = document.createElement('button');
item.classList.add('task');
content.classList.add('content');
deleteBtn.classList.add('deleteBtn');
item.setAttribute('data-id', task.id)
content.textContent = task.content;
deleteBtn.textContent = 'Удалить';
item.appendChild(content);
item.appendChild(deleteBtn);
fragment.appendChild(item);
});
fragmentAppend.appendChild(fragment);
fragmentAppend.addEventListener('click', deleteTask, { capture: true })
}
function deleteTask(e) {
e.stopPropagation();
if (e.target.classList != 'deleteBtn') {
return;
} else {
console.log(2);
const parent = e.target.closest('[data-id').dataset.id;
const deleteChange = tasks.reduce((acc, task) => {
if (acc[task.id] = parent) {
tasks.splice(0, task);
loadTasks();
return;
}
}, {});
}
}
}(tasks));
}());
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container {
width: 1200px;
margin: 0 auto;
}
section.todo {
margin-top: 100px;
}
section.todo .container {
text-align: center;
width: 500px;
}
section.todo .container form {
display: flex;
justify-content: space-between;
margin: 0 auto
}
section.todo .container form input {
padding: 7px 14px;
}
section.todo .container form [name="addTaskBut"] {
background-color: #fff;
border: 1px solid #000;
cursor: pointer;
}
section.todo .container form [name="taskText"] {
width: 440px;
}
section.todo .container .tasks .task {
border: 1px solid #000;
padding: 10px 15px;
margin-top: 10px;
position: relative;
}
section.todo .container .tasks .task .content {
font-family: sans-serif;
width: 300px;
margin: 0 auto;
word-wrap: break-word;
}
section.todo .container .tasks .task .deleteBtn {
background-color: #fff;
border: none;
border-right: 1px solid #000;
border-bottom: 1px solid #000;
padding: 3px 7px;
position: absolute;
top: 0;
left: 0;
cursor: pointer;
outline: none;
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>ToDo</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<header>
<div class="container">
<div class="logo">ToDo</div>
</div>
</header>
<section class="todo">
<div class="container">
<form name="addTask" id="addNewTask">
<input type="submit" name="addTaskBut" value="add">
<input type="text" name="taskText">
</form>
<div class="tasks"></div>
</div>
</section>
<script src="js/app.js"></script>
</body>
</html>
(лучше разворачивать на всю страницу).
Ответы (1 шт):
Автор решения: Grundy
→ Ссылка
В коде смешалось сразу несколько подходов, поэтому и не работает.
const deleteChange = tasks.reduce((acc, task) => {
if (acc[task.id] = parent) {
tasks.splice(0, task);
loadTasks();
return;
}
}, {});
reduceНЕЛЬЗЯ остановить.- в данном случае из функции коллбэка ничего не возвращается. В этом случае на второй итерации
accвсегдаundefined, поэтому и возникает ошибка при попытке обращения к его свойству. - менять массив по которому происходит итерация - не самая лучшая идея, особенно, когда в качестве числа идете попытка передать объект.
Вместо этого кода можно было использовать простой filter
tasks = tasks.filter(task => task.id != parent);
(function() {
// ToDo
let tasks = [];
(function() {
// UI
const addTask = document.getElementById('addNewTask'),
addTaskBut = addTask.elements.addTaskBut,
taskContent = addTask.elements.taskText;
// Events
window.onload = () => {
loadTasks();
};
addTaskBut.addEventListener('click', createTask);
// Functions
function createTask(e) {
e.stopPropagation();
e.preventDefault();
if (!taskContent.value) {
alert('Нельзя создать пустую задачу');
return;
}
const task = {
id: Math.random(),
content: taskContent.value
};
tasks.push(task);
loadTasks();
console.log(tasks);
}
function loadTasks() {
const fragmentAppend = document.querySelector('.tasks');
fragmentAppend.innerHTML = '';
const fragment = tasks.reduce((fragment, task) => {
let item = document.createElement('div'),
content = document.createElement('div'),
deleteBtn = document.createElement('button');
item.classList.add('task');
content.classList.add('content');
deleteBtn.classList.add('deleteBtn');
item.setAttribute('data-id', task.id)
content.textContent = task.content;
deleteBtn.textContent = 'Удалить';
item.appendChild(content);
item.appendChild(deleteBtn);
fragment.appendChild(item);
return fragment;
}, document.createDocumentFragment());
fragmentAppend.appendChild(fragment);
fragmentAppend.addEventListener('click', deleteTask, {
capture: true
})
}
function deleteTask(e) {
e.stopPropagation();
if (e.target.classList != 'deleteBtn') {
return;
} else {
const parent = e.target.closest('[data-id]').dataset.id;
tasks = tasks.filter(task => task.id != parent);
loadTasks();
}
}
}(tasks));
}());
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container {
width: 1200px;
margin: 0 auto;
}
section.todo {
margin-top: 100px;
}
section.todo .container {
text-align: center;
width: 500px;
}
section.todo .container form {
display: flex;
justify-content: space-between;
margin: 0 auto
}
section.todo .container form input {
padding: 7px 14px;
}
section.todo .container form [name="addTaskBut"] {
background-color: #fff;
border: 1px solid #000;
cursor: pointer;
}
section.todo .container form [name="taskText"] {
width: 440px;
}
section.todo .container .tasks .task {
border: 1px solid #000;
padding: 10px 15px;
margin-top: 10px;
position: relative;
}
section.todo .container .tasks .task .content {
font-family: sans-serif;
width: 300px;
margin: 0 auto;
word-wrap: break-word;
}
section.todo .container .tasks .task .deleteBtn {
background-color: #fff;
border: none;
border-right: 1px solid #000;
border-bottom: 1px solid #000;
padding: 3px 7px;
position: absolute;
top: 0;
left: 0;
cursor: pointer;
outline: none;
}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>ToDo</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<header>
<div class="container">
<div class="logo">ToDo</div>
</div>
</header>
<section class="todo">
<div class="container">
<form name="addTask" id="addNewTask">
<input type="submit" name="addTaskBut" value="add">
<input type="text" name="taskText">
</form>
<div class="tasks"></div>
</div>
</section>
<script src="js/app.js"></script>
</body>
</html>