How to 'edit' other item rows? (JS)

107 Views Asked by At

I can edit/update only at the first item row. I can add new item rows but I can not edit/update the new item rows. I added 'console.log(~)' but seems like the other rows are not linked at all.

to edit/update for the new item rows, (where 'editBTN.addEventListener~~'), i think i have to link 'data type' at the edit/update function as well? Please help..

// createItem
function createItem(text, id) {
  const itemRow = document.createElement('li');
  itemRow.setAttribute('class', 'item_row');
  itemRow.setAttribute('data-id', id || Date.now());
  itemRow.innerHTML = `
    <div class="item">
        <button class="list__done" >
          <i class="fa-sharp fa-regular fa-circle-check"></i>
        </button>
        <span class="item_name">${text}</span>

      <div class="button_container">
            <button class="item_edit"}>Edit</button>
            <button class="item_delete" >
                <i class="fas fa-trash-alt" data-id=${id || Date.now()}></i>
            </button>
      </div>
    </div>
    <div class="item_divider"></div>`;
  return itemRow;
}


// edit/Update items
const itemName = document.querySelector('.item_name');
const editBTN = document.querySelector('.item_edit');
const newItemInput = document.createElement('input');

editBTN.addEventListener('click', (event) => {
  if (event.target.innerText === 'Update') {
    itemName.innerText = newItemInput.value;
    newItemInput.value = '';
    editBTN.innerText = 'Edit';
  } else {
    itemName.innerHTML = '';

    newItemInput.type = 'text';
    newItemInput.className = 'newItemInput';
    itemName.appendChild(newItemInput);
    newItemInput.focus();

    editBTN.innerText = 'Update';
  }

  saveItems();
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>TodoList</title>

    <!-- JavaScript -->
    <script type="module" src="script.js" defer></script>
    
  </head>
  <body>
    <section class="list">
      <!-- Header -->
      <header class="header">
        <div class="header__date"></div>
        <div class="header__name">
          Just do it <i class="fa-solid fa-check-double"></i>
        </div>
      </header>
      <!-- Body -->
      <ul class="items">
      </ul>
      <form class="new_form">
        <footer class="footer">
          <input type="text" class="footer_input" />
          <button type="submit" class="footer_button">
            <i class="fas fa-plus"></i>
          </button>
        </footer>
      </form>
    </section>
  </body>
</html>

3

There are 3 best solutions below

1
Muhammad Idrees On BEST ANSWER

It looks like you are trying to create a to-do list with the ability to edit and update the items. The issue you are facing is that the edit/update functionality is only working for the first item row, and not for the new item rows that are added dynamically.

The reason for this is that you are selecting the first item row and its corresponding elements (such as itemName and editBTN) outside the event listener. When you dynamically add new item rows, these variables still refer to the elements from the first item row, and that's why the edit/update functionality only works for the first row.

To fix this, you need to modify your event listener and access the specific elements within the clicked item row. Here's how you can do it:

    const itemsList = document.querySelector('.items');

itemsList.addEventListener('click', (event) => {
  const targetElement = event.target;

  if (targetElement.classList.contains('item_edit')) {
    const itemRow = targetElement.closest('.item_row');
    const itemName = itemRow.querySelector('.item_name');
    const editBTN = itemRow.querySelector('.item_edit');
    const newItemInput = document.createElement('input');

    if (editBTN.innerText === 'Update') {
      itemName.innerText = newItemInput.value;
      newItemInput.value = '';
      editBTN.innerText = 'Edit';
    } else {
      itemName.innerHTML = '';

      newItemInput.type = 'text';
      newItemInput.className = 'newItemInput';
      itemName.appendChild(newItemInput);
      newItemInput.focus();

      editBTN.innerText = 'Update';
    }

    saveItems();
  }
});

With this modification, the event listener is now attached to the itemsList (the parent element) instead of each individual "Edit" button. When you click the "Edit" button, it finds the closest parent item row (.item_row) and then locates the specific elements (.item_name, .item_edit) within that row. This way, the edit/update functionality will work for all the dynamically added item rows as well.

Please note that the saveItems() function is not shown in your provided code, but you need to ensure it saves the changes appropriately to your data storage (e.g., localStorage or a backend database).

0
Gerald Negvesky On

When you use "addEventListener", it only binds to the existing html elements. Since you are adding more elements, those elements are not binded to any listeners. You must use addEventListener every time you create a new element.

0
CHGX6 On

i have been able to regiter events to items that are created at execution time with javascript, like buttons

this is with jquery.

$(document).on('click','selector',functtion(){ });

in that way.

maybe there is an equivalent in vainilla