1

Working on creating a to-do list with JavaScript. I begin with a few default 'to-dos' that I coded into the html file. The structure of the list is like this

<h4 style="text-align: center;">Reminders To Do:</h4>
<p style="text-align: center;">Check off each task after completing it!</p>
<ul id="reminders" class="list-group">
    <div id="task">
         <li class="list-group-item" id="taskCheck"><input type="checkbox" name="task">Take out the trash</li>
    </div>
    <div id="task">
         <li class="list-group-item" id="taskCheck"><input type="checkbox" name="task">Email boss about project</li>
    </div>
    <div id="task">
        <li class="list-group-item" id="taskCheck"><input type="checkbox" name="task">Cancel subscriptions</li>
    </div>
    <div id="task">
        <li class="list-group-item" id="taskCheck"><input type="checkbox" name="task">Go to gym</li>
    </div>
 </ul>

I am able to add new events to this list by creating a form below with an eventListener on 'submit', etc. Everything there works as it should. The issue arises since I have a function in JS that should set the "style: display: "none";" hence removing the task from the list when completed. This works fine for the default events.

let eventForm = document.querySelector('#taskForm');
let eventName = document.querySelector('input[name="newTask"]');
let eventDate = document.querySelector('input[name="taskDate"');
let reminders = document.querySelector('#reminders');
let msg = document.querySelector('.msg');

eventForm.addEventListener('submit', onSubmit);

function onSubmit(e) {
    e.preventDefault();

    if(eventName.value === '' || eventDate.value === '') {
        msg.innerHTML = 'Please complete both fields.';

        setTimeout(() => msg.remove(), 3000);
    } else {
        let div = document.createElement('div');  //structure is ul -> div -> li -> input
        div.setAttribute('id', 'task');

        let li = document.createElement('li');
        li.setAttribute('id', 'taskCheck');
        li.className += 'list-group-item'; //adds the bootstrap class to li
        li.innerHTML += '<input type="checkbox" name="task">'; //since input tag is nested within li element
        li.appendChild(document.createTextNode(`${eventName.value} | ${eventDate.value}`));

        div.appendChild(li); //adds li to a div within the list

        reminders.appendChild(div); //adds div into the list

        //resets form fields to empty for another task
        eventName.value = '';
        eventDate.value = '';

    }
}

Even though I see the new events added through my form, there is no response when I check/ uncheck the box.

My function for removing checked events is as such: note I changed the functionality so instead of not showing the event, I'm testing with console.log();

let reminderList = document.querySelectorAll('#reminders li');
let tasksCheck = document.querySelectorAll('input[type="checkbox"]');


tasksCheck.forEach((task, i) => { //i holds the index of each task in the list

    task.addEventListener('change', () => {
        if(task.checked) {
            console.log('Task completed!');
        } else {
            console.log('Task not completed yet.');
        }
    })
})

I know the post is very long, would really appreciate help with this.

isherwood
  • 58,414
  • 16
  • 114
  • 157
timrockx
  • 51
  • 1
  • 7
  • _"I am able to add new events to this list..."_ - do you mean new **todo items** to the list? Also, it might be easier for the community to assist you on this if you could make a [mcve] in a [runnable stack snippet](https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/), and included clear steps to reproduce, the expected behavior, and the actual behavior. The description now is a bit difficult to follow-- a list of steps would be easier. Good luck, and happy coding! – Alexander Nied Aug 12 '21 at 18:10
  • It may become a good question, if images of new events update to the question. looks like it is working partially? – Nadeem Taj Aug 12 '21 at 18:34

1 Answers1

1

If I understood your question correctly, I think the new tasks are not responding to the click event because you added the event listen before they were created. You can use event delegation to solve this with code similar to the following:

let reminders = document.querySelector('#reminders'); // save the reminders
const handleTaskClick = e => {
if (e.target.tagName.toLowerCase() === 'input') {// check if it is a task element. You can use className here
  const taskInput = e.target;
  const task = taskInput.parentElement.parentElement; // get the task div
  const taskIndex = Array.from(reminders.children).indexOf(task); // convert to an array look for its index
  if(taskInput.checked) {
    console.log('Task completed!', taskIndex);
  } else {
    console.log('Task not completed yet.', taskIndex);
  }
 }
} 
// add the event listener to the reminders wrapper element #remiders
reminders.addEventListener('click', handleTaskClick); 
Ogie
  • 1,304
  • 2
  • 14
  • 17
  • Thanks so much, that ended up being the issue! – timrockx Aug 12 '21 at 20:42
  • Hey sorry to bother again... since my previous method looped with the reminders, I could simply access the index of the task that was checked. But here I have no index to find which task was checked? Do you have any suggestions to get around this? – timrockx Aug 12 '21 at 21:00
  • No worries @timrockx I have added a way for you to retrieve the index of the task – Ogie Aug 13 '21 at 10:55