Редактирование и удаление элементов списка

Есть массив с именами, нужно создать список с элементами этого массива, это сделано.

Конечный результат: в конце списка есть инпут через который можно добавлять новые элементы, все элементы включая новые могут редактироваться и удалятся по нажатию на ссылку рядом с сопутствующим элементом.(удаление еще не доделано, не в нем проблема)

Проблема: как сократить два блока кода (существующих 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 шт):

Автор решения: SwaD

Реализовать редактирование и удаление можно следующим образом:

Функцию обработчик над вынести отдельно и внутри оперировать контекстом 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);
  }
→ Ссылка
Автор решения: Vladislav G.

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

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>

→ Ссылка