skip to Main Content

I am a newbie JavaScript developer. I am creating a ToDo list, and I am stuck in between.

I have created a function to delete all the completed tasks.

Below there’s an array tasks containing various objects that contain information about the tasks.

What I want is if the object contains completion === true, then the same object should be removed from the array tasks. And I want this to be done for every single completed task.

But the problem is that the Array.forEach is removing only the first completed task. The rest completed tasks are as it is.

Thanks in advance if anyone can help me and tell me why is that happening…

Here’s the code.

    const allCompletedTasksOnPage = document.querySelectorAll(".completed");
    let confirmDelete;
    if (allCompletedTasksOnPage.length > 0) {
        confirmDelete = confirm(`Are you sure, you want to delete all ${allCompletedTasksOnPage.length} completed tasks?`);
    };
    if (confirmDelete) {
        tasks.forEach((task) => {
            if (task.completion === true) {
                tasks.splice(tasks.indexOf(task), 1);
            };
        });
        allCompletedTasksOnPage.forEach((task) => {
            task.remove();
        });
    };
});```

3

Answers


  1. If you don’t mind that a new array is created then this is a perfect job for filter:

    tasks = tasks.filter(task => !task.completion);
    

    It takes all elements for which the condition delivers true, which we achieve by inverting task.completion.

    Login or Signup to reply.
  2. You can use Peter B’s answer to get a filtered task array:

    tasks = tasks.filter(task => !task.completion);
    

    This creates a new array that overwrites the previous one.

    But for some reason if you want to keep an original array you can delete elements from it in-place.

    For example you imported an array from a module as a part of your global state, passed an array’s reference to some modules or use for example Vue and an array is a reactive variable you don’t want to overwrite.

    Nowadays I’m moving forward to use const for array variables and modify them in-place not to break any array variables’ references.

    For that use a usual for loop. When you delete an element just decrement the iteration index since the length of the array decreases too:

    for(let i = 0; i < tasks.length; i++){
      tasks[i].completition && tasks.splice(i--, 1);
    }
    
    Login or Signup to reply.
  3. Use while instead foreach because when an item is removed you have to check the same index again.

    if (confirmDelete) {
            var index=0;
            while(index<tasks.length) {
                let task=tasks[index];
                if (task.completion === true) {
                    tasks.splice(index, 1);
                    index--;
                };
                index++;
            };
           
        };
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search