0

I am populating a <ul></ul> with <li></li> using fetch method api request.

The ul looks like the code below:

<ul id="todos" class="collection">
</ul>

The script that populates the todos:

fetch("http://localhost:3000/api/todos")
.then((resp) => resp.json())
.then((data) => {
  let todos = data;
  return todos.map(todo => {
    let liTodo = createNode("li");
    liTodo.innerHTML = '<button class="btn-small remove-todo" onclick="' + deleteTodo(`${todo._id}`) + '">Delete' + '</button>';
    liTodo.classList.add("collection-item");
    append(ulTodos, liTodo);
});

function createNode(element) {
  return document.createElement(element); // Create the type of element you pass in the parameters
}

function append(parent, el) {
  return parent.appendChild(el); // Append the second parameter(element) to the first one
}

function deleteTodo(id) {
  console.log("deleteTodo function called " + id);
}

enter image description here

Problem: Upon loading the page and checking console, I can see that deleteTodo() function is invoked even though I did not click it.

Do you know how can I properly pass the deleteTodo() with the id only when it is clicked?

Any help is greatly appreciated. Thanks.

redshot
  • 2,930
  • 3
  • 31
  • 68

4 Answers4

1

You are invoking the deleteTodo unknowingly. Wrap the on click invocation in an arrow function.

liTodo.innerHTML = '<button class="btn-small remove-todo" onclick="() => deleteTodo(' + `${todo._id}` + ')">Delete' + '</button>';
MjZac
  • 3,476
  • 1
  • 17
  • 28
1

You can convert to an arrow function.

Instead of

function deleteTodo(id) {
  console.log("deleteTodo function called " + id);
}

Use

const deleteTodo = (id) => {
  console.log("deleteTodo function called " + id);
}
Burak Gavas
  • 1,304
  • 1
  • 9
  • 11
  • I don't think this helps, the problem is at invocation time... – V. Sambor Mar 18 '20 at 07:44
  • Hi. Thanks for this but it is still invoked inside the loop – redshot Mar 18 '20 at 07:47
  • Hmm, you are right. Actually, I would recommend you the react way of doing this. You are creating elements with string. Instead, you should create them with JSX (react way) by using 'map' function. That would be more accurate and resolve your problem. – Burak Gavas Mar 18 '20 at 07:54
  • @BurakGavas I'm currently only using ES6 for this. In react, the solution is just to wrap the deleteTodo(id) in an anonymous arrow function inside the map function – redshot Mar 18 '20 at 07:56
  • I mean in your return function you should have a JSX expression like: ` items.map((item, idx) =>
  • // your button and its function here
  • ) ` You should write this inside your JSX – Burak Gavas Mar 18 '20 at 08:01