skip to Main Content

The window.addEventListener is getting executed only on the second click and surprisingly, after I click once on the li element to read the task and again clicking on delete button, then the read task event gets fired up! as I’m keeping the delete button mapped inside the list element.

list element has a click handler to read the task information.

The delete button has its remove task handler. I’m attaching the events to stop event propagation to its parent.

On delete button click only removeTask method should get executed and on read task information only the readTheTask method should get called.

The first problem here is, as I’m using the addEventListener, it only gets executed after the second click.

And the second problem if I remove attaching the eventListeners then on delete button click, the read task event also gets fired up!

How to resolve these issues?? Expecting some genuine solutions. The help would be appreciated. Thanks!

Here’s the => Working Demo

Here’s my code:

window.deleteTask = function deleteTask(id) {
 const deleteButton = document.getElementById(id);
  deleteButton.addEventListener(
    "click",
    (event) => {
      // event.preventDefault();
      let taskAppObj = new ToDoConstructor();
      taskAppObj.removetask(id);
      event.stopPropagation();
    },
    false
  );
};

window.getTaskInfo = function getTaskInfo(id) {
  const li = document.getElementById(`data-${id}`);
  li.addEventListener("click", (event) => {
    let taskAppObj = new ToDoConstructor();
    let task = window.storeContext.find((task) => task.id === id);
    taskAppObj.readTheTask(task);
  });
};

2

Answers


  1. Using createElement instead string literal and you do not pass an initial argument on any Event listener function it always be a event argument, it is a good practice.

    function getTaskList() {
            let tasks = [...window.storeContext];
            console.log("tasl", tasks);
            const taskListUl = document.getElementById("task-elements");
            taskListUl.replaceChildren();//removes the existing li
            if(tasks && tasks.length){
            tasks.forEach(
                    (task) =>{
                        const id = String(task.id)
                        const li = document.createElement('li');
                        const button = document.createElement('button');
                        const span = document.createElement('span');
                        li.ariaLabel = id;
                        button.ariaLabel = id;
                        span.ariaLabel = id;
                        span.textContent = task.title;
                        button.textContent = 'X';
                        li.append(span);
                        li.append(button);
                        li.onclick = window.getTaskInfo;
                        button.onclick = window.deleteTask;
                        taskListUl.append(li);
                    })
           }
      }
    

    ReadTask

    window.getTaskInfo = function getTaskInfo(event) {
        const id = event.target.ariaLabel;
        let taskAppObj = new ToDoConstructor();
        let task = window.storeContext.find((task) => task.id === Number(id));
        taskAppObj.readTheTask(task);
    };
    

    Delete Task

     window.deleteTask = function deleteTask(event) {
        event.stopPropagation();
        const id = event.target.ariaLabel;
        console.log("I am delte function!");
        let taskAppObj = new ToDoConstructor();
        taskAppObj.removetask(Number(id));
     };
    

    Also tested in the codesandbox

    Login or Signup to reply.
  2. setTimeout(function () {
      init();
    }, 1000);
    
    const ToDoConstructor = function () {
      this.toDoList = [
        {
          id: 1,
          title: "Task 1",
          description: "Meditation",
          priority: 1
        },
        {
          id: 2,
          title: "Task 2",
          description: "Room Cleaning",
          priority: 2
        },
        {
          id: 3,
          title: "Task 3",
          description: "Washing Clothes",
          priority: 3
        },
        {
          id: 4,
          title: "Task 4",
          description: "Studying",
          priority: 4
        }
      ];
      this.readTheTask = function (params) {
        const taskDisplayDiv = document.getElementById("task-info");
        const titleSpan = document.getElementById("titleSpan");
        const descrSpan = document.getElementById("descrSpan");
        const prioritySpan = document.getElementById("prioritySpan");
    
        taskDisplayDiv.setAttribute("class", "visible");
    
        titleSpan.innerHTML = params.title;
        descrSpan.innerHTML = params.description;
        prioritySpan.innerHTML = params.priority;
      };
      this.removetask = function (id) {
        // This function accepts id of a task to be removed from toDoList
        if (window.storeContext.length > 0) {
          this.toDoList = [...window.storeContext];
        }
    
        
    
        this.toDoList = this.toDoList.filter((element) => element.id !== id);
    
        window.storeContext = [...this.toDoList];
    
       
    
        getTaskList();
      };
    };
    
    function init() {
      const taskAppObj = new ToDoConstructor();
      window.storeContext = [...taskAppObj.toDoList];
      getTaskList();
    }
    document.addEventListener("DOMContentLoaded", function () {
      const taskListUl = document.getElementById("task-elements");
    
      taskListUl.addEventListener("click", function (event) {
        if (event.target.tagName === "BUTTON") {
          const id = event.target.id;
          deleteTask(id);
        } else if (event.target.tagName === "LI") {
          const id = event.target.id.split("-")[1]; // Extract the ID from the element's ID
          getTaskInfo(id);
        }
      });
    });
    
    function deleteTask(id) {
      let taskAppObj = new ToDoConstructor();
      taskAppObj.removetask(id);
    }
    
    function getTaskInfo(id) {
      let taskAppObj = new ToDoConstructor();
      let task = window.storeContext.find((task) => task.id == id);
      taskAppObj.readTheTask(task);
    }
    
    function getTaskList() {
      let tasks = [...window.storeContext];
      console.log("tasks", tasks);
      const taskListUl = document.getElementById("task-elements");
      taskListUl.innerHTML = "";
    
      if (tasks && tasks.length > 0) {
        tasks.forEach((task) => {
          const listItem = document.createElement("li");
          listItem.id = `data-${task.id}`;
    
          const taskTitle = document.createElement("span");
          taskTitle.innerText = task.title;
    
          const deleteButton = document.createElement("button");
          deleteButton.innerText = "x";
    
          // Attach a click event listener to the list item
          listItem.addEventListener("click", function (event) {
         
            if (event.target.tagName === "SPAN") {
              getTaskInfo(task.id);
            }
          });
    
          // Attach a click event listener to the Delete button
          deleteButton.addEventListener("click", function (event) {
            event.stopPropagation(); // Prevent the click event on the list item from firing
            deleteTask(task.id);
          });
    
          listItem.appendChild(taskTitle);
          listItem.appendChild(deleteButton);
          taskListUl.appendChild(listItem);
        });
      }
    }
    
    document.getElementById("app").innerHTML = `
    <h1>Tasks</h1>
    <div class=task-display-div>
      <div class=task-col>
        <header>Task List</header>
        <div>
          <ul id=task-elements>
          </ul>
        </div>
      </div>
      <div class=task-col>
        <header>
          Task Details:
        </header>
        <div id=task-info class=hidden>
          <div>
            <h5>Task Title: </h5><SPAN id=titleSpan></SPAN>
          </div>
          <div>
            <h5>Task Details: </h5><SPAN id=descrSpan></SPAN>
          </div>
          <div>
            <h5>It is a prio <SPAN id=prioritySpan></SPAN> task.</h5>
          </div>
      </div>
    </div>
    `;
    body {
      font-family: sans-serif;
    }
    
    .task-display-div {
      display: flex;
      width: 90%;
    }
    
    .task-col {
      padding: 0px 10px;
      border-right: 1px solid;
    }
    <!DOCTYPE html>
    <html>
      <head>
        <title>Parcel Sandbox</title>
        <meta charset="UTF-8" />
      </head>
    
      <body>
        <div id="app"></div>
    
      </body>
    </html>

    By doing some changes in your code it is working in single click (check result on full page)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search