Learn localStorage by Building a Todo App - Step 51

Tell us what’s happening:

Step 51
If the user attempts to edit a task but decides not to make any changes before closing the form, there is no need to display the modal with the Cancel and Discard buttons.
Inside the closeTaskFormBtn event listener, use const to create another variable named formInputValuesUpdated. Check if the user made changes while trying to edit a task by verifying that the titleInput value is not equal to currentTask.title, or the dateInput value is not equal to currentTask.date, or the descriptionI

I am receiving the below errors when trying to submit my code.

  1. Your formInputValuesUpdated variable should check if titleInput.value is not equal to currentTask.title.
  2. Your formInputValuesUpdated variable should check if titleInput.value is not equal to currentTask.title or dateInput.value is not equal to currentTask.date.
    // tests completed

I am not really clear what they are wanting me to do beyond this.

Your code so far

<!-- file: index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Learn localStorage by Building a Todo App</title>
  <link rel="stylesheet" href="styles.css" />
</head>

<body>
  <main>
    <h1>Todo App</h1>
    <div class="todo-app">
      <button id="open-task-form-btn" class="btn large-btn">
        Add New Task
      </button>
      <form class="task-form hidden" id="task-form">
        <div class="task-form-header">
          <button id="close-task-form-btn" class="close-task-form-btn" type="button" aria-label="close">
            <svg class="close-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48px" height="48px"><path fill="#F44336" d="M21.5 4.5H26.501V43.5H21.5z" transform="rotate(45.001 24 24)" /><path fill="#F44336" d="M21.5 4.5H26.5V43.501H21.5z" transform="rotate(135.008 24 24)" /></svg>
          </button>
        </div>
        <div class="task-form-body">
          <label class="task-form-label" for="title-input">Title</label>
          <input required type="text" class="form-control" id="title-input" value="" />
          <label class="task-form-label" for="date-input">Date</label>
          <input type="date" class="form-control" id="date-input" value="" />
          <label class="task-form-label" for="description-input">Description</label>
          <textarea class="form-control" id="description-input" cols="30" rows="5"></textarea>
        </div>
        <div class="task-form-footer">
          <button id="add-or-update-task-btn" class="btn large-btn" type="submit">
            Add Task
          </button>
        </div>
      </form>
      <dialog id="confirm-close-dialog">
        <form method="dialog">
          <p class="discard-message-text">Discard unsaved changes?</p>
          <div class="confirm-close-dialog-btn-container">
            <button id="cancel-btn" class="btn">
              Cancel
            </button>
            <button id="discard-btn" class="btn">
              Discard
            </button>
          </div>
        </form>
      </dialog>
      <div id="tasks-container"></div>
    </div>
  </main>
  <script src="script.js"></script>
</body>

</html>

:root {
  --white: #fff;
  --light-grey: #f5f6f7;
  --dark-grey: #0a0a23;
  --yellow: #f1be32;
  --golden-yellow: #feac32;
}

*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background-color: var(--dark-grey);
}

main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

h1 {
  color: var(--light-grey);
  margin: 20px 0 40px 0;
}

.todo-app {
  background-color: var(--white);
  width: 300px;
  height: 350px;
  border: 5px solid var(--yellow);
  border-radius: 8px;
  padding: 15px;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.btn {
  cursor: pointer;
  width: 100px;
  margin: 10px;
  color: var(--dark-grey);
  background-color: var(--golden-yellow);
  background-image: linear-gradient(#fecc4c, #ffac33);
  border-color: var(--golden-yellow);
  border-width: 3px;
}

.btn:hover {
  background-image: linear-gradient(#ffcc4c, #f89808);
}

.large-btn {
  width: 80%;
  font-size: 1.2rem;
  align-self: center;
  justify-self: center;
}

.close-task-form-btn {
  background: none;
  border: none;
  cursor: pointer;
}

.close-icon {
  width: 20px;
  height: 20px;
}

.task-form {
  display: flex;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: var(--white);
  border-radius: 5px;
  padding: 15px;
  width: 300px;
  height: 350px;
  flex-direction: column;
  justify-content: space-between;
  overflow: auto;
}

.task-form-header {
  display: flex;
  justify-content: flex-end;
}

.task-form-body {
  display: flex;
  flex-direction: column;
  justify-content: space-around;
}

.task-form-footer {
  display: flex;
  justify-content: center;
}

.task-form-label,
#title-input,
#date-input,
#description-input {
  display: block;
}

.task-form-label {
  margin-bottom: 5px;
  font-size: 1.3rem;
  font-weight: bold;
}

#title-input,
#date-input,
#description-input {
  width: 100%;
  margin-bottom: 10px;
  padding: 2px;
}

#confirm-close-dialog {
  padding: 10px;
  margin: 10px auto;
  border-radius: 15px;
}

.confirm-close-dialog-btn-container {
  display: flex;
  justify-content: center;
  margin-top: 10px;
}

.discard-message-text {
  font-weight: bold;
  font-size: 1.5rem;
}

#tasks-container {
  height: 100%;
  overflow-y: auto;
}

.task {
  margin: 5px 0;
}

.hidden {
  display: none;
}

@media (min-width: 576px) {
  .todo-app,
  .task-form {
    width: 400px;
    height: 450px;
  }

  .task-form-label {
    font-size: 1.5rem;
  }

  #title-input,
  #date-input {
    height: 2rem;
  }

  #title-input,
  #date-input,
  #description-input {
    padding: 5px;
    margin-bottom: 20px;
  }
}
/* file: styles.css */


const taskForm = document.getElementById("task-form");
const confirmCloseDialog = document.getElementById("confirm-close-dialog");
const openTaskFormBtn = document.getElementById("open-task-form-btn");
const closeTaskFormBtn = document.getElementById("close-task-form-btn");
const addOrUpdateTaskBtn = document.getElementById("add-or-update-task-btn");
const cancelBtn = document.getElementById("cancel-btn");
const discardBtn = document.getElementById("discard-btn");
const tasksContainer = document.getElementById("tasks-container");
const titleInput = document.getElementById("title-input");
const dateInput = document.getElementById("date-input");
const descriptionInput = document.getElementById("description-input");

const taskData = [];
let currentTask = {};

const addOrUpdateTask = () => {
  const dataArrIndex = taskData.findIndex((item) => item.id === currentTask.id);
  const taskObj = {
    id: `${titleInput.value.toLowerCase().split(" ").join("-")}-${Date.now()}`,
    title: titleInput.value,
    date: dateInput.value,
    description: descriptionInput.value,
  };

  if (dataArrIndex === -1) {
    taskData.unshift(taskObj);
  } else {
    taskData[dataArrIndex] = taskObj;
  }

  updateTaskContainer()
  reset()
};

const updateTaskContainer = () => {
  tasksContainer.innerHTML = "";

  taskData.forEach(
    ({ id, title, date, description }) => {
        tasksContainer.innerHTML += `
        <div class="task" id="${id}">
          <p><strong>Title:</strong> ${title}</p>
          <p><strong>Date:</strong> ${date}</p>
          <p><strong>Description:</strong> ${description}</p>
          <button onclick="editTask(this)" type="button" class="btn">Edit</button>
          <button onclick="deleteTask(this)" type="button" class="btn">Delete</button> 
        </div>
      `
    }
  );
};


const deleteTask = (buttonEl) => {
  const dataArrIndex = taskData.findIndex(
    (item) => item.id === buttonEl.parentElement.id
  );

  buttonEl.parentElement.remove();
  taskData.splice(dataArrIndex, 1);
}

const editTask = (buttonEl) => {
    const dataArrIndex = taskData.findIndex(
    (item) => item.id === buttonEl.parentElement.id
  );

  currentTask = taskData[dataArrIndex];

  titleInput.value = currentTask.title;
  dateInput.value = currentTask.date;
  descriptionInput.value = currentTask.description;

  addOrUpdateTaskBtn.innerText = "Update Task";

  taskForm.classList.toggle("hidden");  
}

const reset = () => {
  titleInput.value = "";
  dateInput.value = "";
  descriptionInput.value = "";
  taskForm.classList.toggle("hidden");
  currentTask = {};
}

openTaskFormBtn.addEventListener("click", () =>
  taskForm.classList.toggle("hidden")
);

closeTaskFormBtn.addEventListener("click", () => {
  const formInputsContainValues = titleInput.value || dateInput.value || descriptionInput.value;
const formInputValuesUpdated = 
titleInput.value !== currentTask.title || 
dateInput.value !== currentTask.date ||
descriptionInput.value !== currentTask.description
  if (formInputsContainValues) {
    confirmCloseDialog.showModal();
  } else {
    reset();
  }
});

cancelBtn.addEventListener("click", () => confirmCloseDialog.close());

discardBtn.addEventListener("click", () => {
  confirmCloseDialog.close();
  reset()
});

taskForm.addEventListener("submit", (e) => {
  e.preventDefault();

  addOrUpdateTask();
});
/* file: script.js */
// User Editable Region

const formInputValuesUpdated = 
titleInput.value !== currentTask.title || 
dateInput.value !== currentTask.date ||
descriptionInput.value !== currentTask.description

// User Editable Region

Your browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0

Challenge Information:

Learn localStorage by Building a Todo App - Step 51

Welcome to the forum :wave:

Inside the closeTaskFormBtn event listener,

It looks like you moved out of this closure?

Hello, thank you for the reply. I am not sure what all you mean. The below code is what I added, and I placed it in the designated area. I did not make any alterations to other parts of the code.

const formInputValuesUpdated =
titleInput.value !== currentTask.title ||
dateInput.value !== currentTask.date ||
descriptionInput.value !== currentTask.description;

Here’s the bottom of your code, and the lines of code you reference:

But this is not in the closeTaskFormBtn event listener, it’s way at the bottom not in any function at all.

Scroll up and here it is again in the correct place:

I’m not sure if this is the only problem yet, but you can start there

1 Like

Thank you, it’s not actually like that in the Step. I placed the entire javascript code, then I placed the portion that I added in the “user editable region.” Within the step, the code is in the “closeTaskFormBtn” event listener only.

can you please post the whole code in the file?

When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

You can also use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks (`) are not single quotes (').

Hello, thank you for the response. I do not believe that I can edit a post yet. I read that new users are not able to and I do not see a way to do so. Once I am able to make edits, I will add the backticks.

I also did post the entire code. The attached portion is strictly the portion that I am working on.

You can select the full code from the step and copy/paste it into a new comment here.

We are not able to tell from what you’ve shared here if it’s in the correct location.

you do not need to edit a previous post, post the whole code in a new post

Is this what you all need?

const taskForm = document.getElementById("task-form");
const confirmCloseDialog = document.getElementById("confirm-close-dialog");
const openTaskFormBtn = document.getElementById("open-task-form-btn");
const closeTaskFormBtn = document.getElementById("close-task-form-btn");
const addOrUpdateTaskBtn = document.getElementById("add-or-update-task-btn");
const cancelBtn = document.getElementById("cancel-btn");
const discardBtn = document.getElementById("discard-btn");
const tasksContainer = document.getElementById("tasks-container");
const titleInput = document.getElementById("title-input");
const dateInput = document.getElementById("date-input");
const descriptionInput = document.getElementById("description-input");

const taskData = [];
let currentTask = {};

const addOrUpdateTask = () => {
  const dataArrIndex = taskData.findIndex((item) => item.id === currentTask.id);
  const taskObj = {
    id: `${titleInput.value.toLowerCase().split(" ").join("-")}-${Date.now()}`,
    title: titleInput.value,
    date: dateInput.value,
    description: descriptionInput.value,
  };

  if (dataArrIndex === -1) {
    taskData.unshift(taskObj);
  } else {
    taskData[dataArrIndex] = taskObj;
  }

  updateTaskContainer()
  reset()
};

const updateTaskContainer = () => {
  tasksContainer.innerHTML = "";

  taskData.forEach(
    ({ id, title, date, description }) => {
        tasksContainer.innerHTML += `
        <div class="task" id="${id}">
          <p><strong>Title:</strong> ${title}</p>
          <p><strong>Date:</strong> ${date}</p>
          <p><strong>Description:</strong> ${description}</p>
          <button onclick="editTask(this)" type="button" class="btn">Edit</button>
          <button onclick="deleteTask(this)" type="button" class="btn">Delete</button> 
        </div>
      `
    }
  );
};


const deleteTask = (buttonEl) => {
  const dataArrIndex = taskData.findIndex(
    (item) => item.id === buttonEl.parentElement.id
  );

  buttonEl.parentElement.remove();
  taskData.splice(dataArrIndex, 1);
}

const editTask = (buttonEl) => {
    const dataArrIndex = taskData.findIndex(
    (item) => item.id === buttonEl.parentElement.id
  );

  currentTask = taskData[dataArrIndex];

  titleInput.value = currentTask.title;
  dateInput.value = currentTask.date;
  descriptionInput.value = currentTask.description;

  addOrUpdateTaskBtn.innerText = "Update Task";

  taskForm.classList.toggle("hidden");  
}

const reset = () => {
  titleInput.value = "";
  dateInput.value = "";
  descriptionInput.value = "";
  taskForm.classList.toggle("hidden");
  currentTask = {};
}

openTaskFormBtn.addEventListener("click", () =>
  taskForm.classList.toggle("hidden")
);

closeTaskFormBtn.addEventListener("click", () => {
  const formInputsContainValues = titleInput.value || dateInput.value || descriptionInput.value;
const formInputValuesUpdated = 
titleInput.value !== currentTask.title || 
dateInput.value !== currentTask.date ||
descriptionInput.value !== currentTask.description;
  if (formInputsContainValues) {
    confirmCloseDialog.showModal();
  } else {
    reset();
  }
});

cancelBtn.addEventListener("click", () => confirmCloseDialog.close());

discardBtn.addEventListener("click", () => {
  confirmCloseDialog.close();
  reset()
});

taskForm.addEventListener("submit", (e) => {
  e.preventDefault();

  addOrUpdateTask();
});

can you try putting the new code for this step all on one line?

1 Like

I had to break it out into two lines, but that did it. Thank you so much.

What do you mean i have a similar problem