1

I'm running into a problem where the toggle logic is broken. Simple todo-list, on click you should get the toggle of isCompleted. It happens right for the first item, but then it seems the value of isDone is random. Moreover, the changed state doesn't stay if I refresh. But when I console.log the returned object from the update, the field is correctly changed.

function updateTodo(task) {
  //const updateUrl = "/api/todos/" + task.data("id");
  const isDone = !(task.data("completed"));
  const updateData = {
    isCompleted: isDone
  };
  //$.ajax({
      //method: "PUT",
      //url: updateUrl,
      //data: updateData
    //})
  task.toggleClass("done");
  task.data("completed", isDone);
  console.log("task.data completed:" + task.data("completed"));
}

// change status on todo
$("#todo-list").on("click", "li", function() {
  updateTodo($(this));
});
body {
  font-family: "Lato", sans-serif;
  margin: 0;
  padding: 0;
  background-color: #efefef;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

header {
  margin-bottom: 20px;
  width: 50%;
  text-align: center;
}

header h1 {
  font-size: 3em;
  color: purple;
  font-weight: 500;
  margin-bottom: 0px;
}

header h1 span {
  font-weight: 800;
}

header h2 {
  font-size: 1.2em;
  font-weight: 400;
  color: purple;
}

section {
  width: 50%;
  text-align: center;
  padding: 20px;
  margin-bottom: 20px;
}

.wrap {
  display: inline-block;
  /*  centering  */
  position: absolute;
  left: 50%;
  margin-right: 50%;
  transform: translate(-50%, -50%);
}

input {
  /*  cleaning up  */
  outline: none;
  border: none;
  padding: 20px;
  font-size: 24px;
  /*  customize  */
  background: transparent;
  border-bottom: 1px solid #fff;
  color: purple;
  z-index: 20;
}

.bg {
  /*   position */
  position: absolute;
  top: 0%;
  height: 100%;
  width: 0;
  /*   customize */
  background: #fff;
  transition: width 0.6s cubic-bezier(0.52, -0.43, 0.47, 1.29);
  z-index: -2;
}

input:focus+.bg {
  background: #fff;
  width: 100%;
}

input::-webkit-input-placeholder {
  color: #fff;
  transition: color .3s ease;
}

input:focus::-webkit-input-placeholder {
  color: transparent;
}


/* List */

#todo-list {
  width: 50%;
  list-style: none;
  margin: 0;
  padding: 0;
}

#todo-list li {
  height: 60px;
  line-height: 60px;
  font-size: 1.5em;
  background-color: white;
  margin-bottom: 4px;
  box-shadow: 1px 1px 1px silver;
  color: purple;
}

#todo-list li.done {
  background-color: #efefef;
  text-decoration: line-through;
  box-shadow: none;
  border: 1px solid lightgray;
}


/* Delete buton */

#todo-list li span.delete {
  display: inline-block;
  background-color: crimson;
  color: white;
  text-align: center;
  height: 60px;
  width: 0px;
  left: -60px;
  margin-right: 20px;
  transition: 0.2s ease-in;
  opacity: 0;
}

#todo-list li:hover span.delete {
  width: 60px;
  opacity: 1;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Todo API</title>
  <link href="app.css" rel="stylesheet" type="text/css">
  <script src="http://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
</head>

<body>
  <header>
    <h1>todo<span>list</span></h1>
    <h2>simple todo-list built with node</h2>
  </header>
  <section>
    <div class="wrap">
      <input type="text" id="todo-input" placeholder="What should you do ?">
      <div class="bg"></div>
      </div>
  </section>
  <ul id="todo-list">
    <li class="task"><span class="delete">X</span>Debug code</li>
    <li class="task"><span class="delete">X</span>Try this one</li>
  </ul>
</body>

</html>

Listener:

$("#todo-list").on("click", "li", function () {
    updateTodo($(this));
});

AJAX request and toggle:

function updateTodo(task) {
    const updateUrl = "/api/todos/" + task.data("id");
    const isDone = !(task.data("completed"));
    const updateData = {isCompleted: isDone};
    $.ajax({
        method: "PUT",
        url: updateUrl,
        data: updateData
    })
        .then(function (todo) {
            console.log(todo);
            task.toggleClass("done");
            task.data("completed", isDone);
            console.log("task Data completed:" + task.data("completed"));
        })
        .catch(function (err) {
            console.log(err);
        });
}

The update route :

exports.updateTodo = function (req, res) {
    db.Todo.findByIdAndUpdate(req.params.todoId, req.body, {new: true})
        .then(function (todo) {
            res.json(todo);
        })
        .catch(function (err) {
            res.send(err);
        });
}

I feel dumb trying to solve this for so long. I rewrite the code step by step, but I don't have a clue what's wrong.

Someone can give me a hint?

Thanks a lot for your time ! Cheers

3
  • No need to include the back end code here, or tag the question as such. You know already that's not where the issue is, so the question really needs to focus on the front end code. Really easy to produce a verifiable example here Commented May 13, 2018 at 10:56
  • See Introducing Runnable JavaScript, CSS, and HTML Code Snippets Commented May 13, 2018 at 10:59
  • not sure at all that the front-end code is wrong. WHen I check the values of the objects in the db it's chaotic. The code snippet shows it runs well without calling the api. Commented May 13, 2018 at 12:42

1 Answer 1

1

Okay my bad. I really needed to step away a little.

Truth is, I made an mistake when checking the boolean. In the updateTodo function I checked the field of the object in place of the data assigned to the li task:

if (task.isCompleted) {
    task.addClass("done");
}

What should have been :

if (task.data("completed") {
    task.addClass("done");
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.