Редактирование и удаление элементов списка
Есть массив с именами, нужно создать список с элементами этого массива, это сделано.
Конечный результат: в конце списка есть инпут через который можно добавлять новые элементы, все элементы включая новые могут редактироваться и удалятся по нажатию на ссылку рядом с сопутствующим элементом.(удаление еще не доделано, не в нем проблема)
Проблема: как сократить два блока кода (существующих li и добавленных) чтобы не переписывать функцию несколько раз, не получается их соединить, если можно как-то вынести функцию за пределы for, скажите пожалуйста. Также при добавлении ссылки на удаление ссылка добавляется только в уже существующие li, игнорируя добавленные.
let parent = document.querySelector('ul');
let add = document.getElementById('input');
let array = ['Nani', 'Tom', 'Itan', 'Lilo'];
for (let elem of array) {
let li = document.createElement('li');
li.textContent = elem;
parent.append(li)
li.addEventListener('click', func);
function func() {
let input = document.createElement('input');
input.value = li.textContent;
li.textContent = '';
li.append(input);
input.addEventListener('blur', function() {
li.textContent = input.value;
li.addEventListener('click', func)
})
li.removeEventListener('click', func)
}
}
add.addEventListener('blur', function() {
let li = document.createElement('li');
li.textContent = add.value;
parent.append(li)
li.addEventListener('click', func);
function func() {
let input = document.createElement('input');
input.value = li.textContent;
li.textContent = '';
li.append(input);
input.addEventListener('blur', function() {
li.textContent = input.value;
li.addEventListener('click', func)
})
li.removeEventListener('click', func)
}
})
let lis = document.querySelectorAll('ul li')
for (let li of lis) {
let link = document.createElement('a');
link.href = '';
link.textContent = 'delite';
li.append(link)
}
<ul id="parent"></ul>
<input id="input">
Ответы (2 шт):
Реализовать редактирование и удаление можно следующим образом:
Функцию обработчик над вынести отдельно и внутри оперировать контекстом this из обработчиков
Так же отдельно вынести функцию по созданию элементов списка и созданию ссылки удаления элемента
Текст из списка я обернул в тег span, что бы не удалять каждый раз все и заново создавать текст и ссылку. Теперь меняется текст на инпут и обратно, все остально остается
let parent = document.querySelector('ul');
let add = document.getElementById('input');
let array = ['Nani', 'Tom', 'Itan', 'Lilo'];
function createLink(li) {
let link = document.createElement('a');
link.href = '';
link.textContent = 'delite';
link.addEventListener('click', (e) => {
e.preventDefault();
li.remove()
});
li.append(link);
}
function func() {
const item = this;
let input = document.createElement('input');
input.value = item.textContent;
item.textContent = '';
item.append(input);
input.addEventListener('blur', function() {
item.textContent = input.value;
item.addEventListener('click', func);
})
item.removeEventListener('click', func);
}
function createLi(elem) {
let li = document.createElement('li');
const span = document.createElement('span');
span.textContent = typeof elem === 'string' ? elem : this.value;
span.addEventListener('click', func);
li.append(span);
createLink(li);
parent.append(li);
}
array.forEach(el => createLi(el));
add.addEventListener('blur', createLi);
<ul id="parent"></ul>
<input id="input">
Почему не появлялась ссылка на удаление? - Потому что при создании новых элементов списка вы не добавляете ссылку, а после редактирования элемента, вы полностью зачищали родительский блок и добавляли туда текст
Если вам не нравится строка const item = this;
в функции func, то можно воспользоваться стрелочной фукнцией для создания обработчика события, т.к. у стрелочных функций нет собственного контекста
function func() {
let input = document.createElement('input');
input.value = this.textContent;
this.textContent = '';
this.append(input);
input.addEventListener('blur', () => {
this.textContent = input.value;
this.addEventListener('click', func);
})
this.removeEventListener('click', func);
}
Вот, посмотрите этот вариант, я не особо менял логику вашего кода, так что тут тоже есть еще над чем подумать. Просто оптимизировал код и немного добавил.
PS: я так и не смог удержаться и заменил ссылки на кнопки, простите)
const parent = document.querySelector('ul');
const add = document.querySelector('input');
const array = ['Nani', 'Tom', 'Itan', 'Lilo'];
const liTemplate = document.querySelector('#item-template').content.querySelector('.list-item');
function setEditMode(txtElem) {
const editElem = document.createElement('input');
editElem.value = txtElem.textContent;
editElem.addEventListener('blur', () => resetEditMode(txtElem, editElem));
txtElem.style.display = 'none';
txtElem.after(editElem);
editElem.focus();
}
function resetEditMode(txtElem, editElem) {
txtElem.textContent = editElem.value;
editElem.remove();
txtElem.style.display = 'block';
}
function createItem(name) {
const item = liTemplate.cloneNode(true);
const txtElem = item.querySelector('.item-txt');
txtElem.textContent = name;
txtElem.addEventListener('click', () => {setEditMode(txtElem)});
item.querySelector('.del-button').addEventListener('click', () => item.remove());
return item;
}
function addItems(names) {
names.forEach(name => {
const item = createItem(name);
parent.append(item);
});
}
add.addEventListener('blur', () => addItems([add.value]));
addItems(array);
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
padding: 30px;
}
.list-item {
display: flex;
gap: 20px;
padding-bottom: 10px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<ul class="list"></ul>
<input class="list-add" type="text">
<template id="item-template">
<li class="list-item">
<p class="item-txt"></p>
<button class="del-button" type="button">delete</button>
</li>
</template>
<script src="index.js"></script>
</body>
</html>