How to push the tasklist into an array with the add button?

Viewed 92

The function addTask() is the function that when the user clicks the "+" button it adds the list to the array. I have a render function that renders the to-do list when the "+" is added. I sat and thought about how I could do this.

doing the taskList.push()``` in the ```function addTask()``` might work, but the issue I am having is I am not sure how to push the elements of the ```function renderList(list)``` into the taskList.push()```.

I am missing something in this approach, but I am not sure what. I know I need to access the ```let newtask```` and add that bit to the array.

HTML

 <div class="form">
        <input class ="user-input" type="text">
        <input class="date" type="date">
        <input class="time" type="time">
        <button onclick="addTask()" class="add" id="add">+</button>
    </div>

    <div class="list"></div>

JS

//local storage key
const STORAGE_KEY = "tasks-storage-key";

// variables object
const el = {
  form: document.querySelector(".form"),
  input: document.querySelector(".user-input"),
  list: document.querySelector(".list"),
  date: document.querySelector(".date"),
  time: document.querySelector(".time"),
};

//Create ID

const createId = () =>
  `${Math.floor(Math.random() * 10000)}${new Date().getTime()}`;

//variable of empty array that gets new task
let taskList = JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? "[]");

function makeNewTask() {
  const data = {
    id: createId(),
    taskNew: el.input.value,
    taskDate: el.date.value,
    taskTime: el.time.value,
  };

  return data;
}

//function that creates new tasks with date and time
function display() {
   data = makeNewTask();
   taskList.push(data); 
   renderList(taskList); 
   storeList();
}

function renderList(list) {
  list.forEach(function (data) {
    const tasks = document.createElement("div");
    let newtask = (tasks.innerHTML = `
         <div class="task-content">
          <div class="task" data-id="${data.id}">
          <div class="new-task-created">${data.taskNew}</div>
          <label class="due-date">${data.taskDate}</label>
          <label class="due-time">${data.taskTime}</label>
      </div>
  
      <div class="action-buttons">
          <button onclick="editItem(event)" class="edit" data-id="${data.id}">Edit</button>
          <button onclick="deleteItem(event)" class="delete" data-id="${data.id}">Delete</button>
          <button onclick="completeItem(event)" class="complete" data-id="${data.id}">Complete</button>
      </div>
  </div>`);
    el.list.appendChild(tasks);
  });
}

//event listner that listens for add button.
function addTask() {
   taskList.push(list);
}

//function that stores task list.
function storeList() {
  window.localStorage.setItem(STORAGE_KEY, JSON.stringify(taskList));
}

//function that removes task from array with delete button.

function deleteItem() {
  let removeitem = document.querySelector(".task-content");
  removeitem.parentNode.removeChild(removeitem);
  window.localStorage.removeItem(STORAGE_KEY);
}

//function that removes stored task when deleted.

//function that that edits tasks with date and time.
function editItem() {}

//function that that completes task.
function completeItem(event) {
  const element = event.target.closest(".task-content");
  console.log(element);
  let taskItem = element.querySelector(".new-task-created");
  let dateItem = element.querySelector(".due-date");
  let timeItem = element.querySelector(".due-time");
  // style..
  taskItem.style.textDecoration = "line-through";
  dateItem.style.textDecoration = "line-through";
  timeItem.style.textDecoration = "line-through";
}

This is the error I get.

enter image description here

enter image description here

2 Answers

There are a few issues with your code, but let's start with the error:

Well the issue is that addTask function does not receive a list parameter that you are trying to push. I think you want to call makeNewTask() there instead of passing that list that is undefined.

  //event listner that listens for add button.
  function addTask() {
     taskList.push(makeNewTask());
  }

The next problem is that display() is never called. Also, why are you creating an empty task when calling display? The display function is redundant, you should only call renderList(taskList). You should call storeList() only when it changes (creation of new task or removal of one).

Next problem is in your renderList() function. You are assigning that newTask variable that you never actually use. Also if you're appending children to the main element in a forEach on that list, it will keep adding new lists of elements. I don't think you want that.

function renderList() {
    el.list.innerHTML = taskList.map(function (data) {
        return `<div class="task">
            <div class="task-content">
                <div class="task" data-id="${data.id}">
                <div class="new-task-created">${data.taskNew}</div>
                <label class="due-date">${data.taskDate}</label>
                <label class="due-time">${data.taskTime}</label>
            </div>
    
            <div class="action-buttons">
                <button onclick="editItem(event)" class="edit" data-id="${data.id}">Edit</button>
                <button onclick="deleteItem(event)" class="delete" data-id="${data.id}">Delete</button>
                <button onclick="completeItem(event)" class="complete" data-id="${data.id}">Complete</button>
            </div>
        </div>`;
    });
}

Also, renderList should use the taskList instead of receiving a list parameter since you're already storing the taskList globally (which is not great either).

The final working code should be something like this (added some comments as well -- I suggest using classes for structuring your data but I'll leave that up to you):

//local storage key
const STORAGE_KEY = "tasks-storage-key";

// variables object
const el = {
    form: document.querySelector(".form"),
    input: document.querySelector(".user-input"),
    list: document.querySelector(".list"),
    date: document.querySelector(".date"),
    time: document.querySelector(".time"),
};

//Create ID

const createId = () => `${Math.floor(Math.random() * 10000)}${new Date().getTime()}`;

//variable of empty array that gets new task
let taskList = JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? "[]");

// This should be called initially after you read the data from localstorage in order to display the initial data if you have any.
renderList();

function makeNewTask() {
    const data = {
        id: createId(),
        taskNew: el.input.value,
        taskDate: el.date.value,
        taskTime: el.time.value,
    };

    return data;
}

function renderList() {
    // actually reset the list innerHTML to the new list (in order to facilitate removing / adding -- not very efficient)
    el.list.innerHTML = taskList.map(function (data) {
        return `<div class="task">
            <div class="task-content">
                <div class="task" data-id="${data.id}">
                <div class="new-task-created">${data.taskNew}</div>
                <label class="due-date">${data.taskDate}</label>
                <label class="due-time">${data.taskTime}</label>
            </div>
    
            <div class="action-buttons">
                <button onclick="editItem(event)" class="edit" data-id="${data.id}">Edit</button>
                <button onclick="deleteItem(event)" class="delete" data-id="${data.id}">Delete</button>
                <button onclick="completeItem(event)" class="complete" data-id="${data.id}">Complete</button>
            </div>
        </div>`;
    });
}

//event listner that listens for add button.
function addTask() {
    taskList.push(makeNewTask());
    // store the list on localstorage because data changed
    storeList();
    // render list again because you've added a new entry
    renderList();
}

//function that removes task from array with delete button.
function deleteItem(event) {
    taskList.splice(taskList.indexOf(event.target.dataset.id), 1);
    // store the list on localstorage because data changed
    storeList();
    // render list again because you've removed an entry
    renderList();
}

//function that stores task list.
function storeList() {
    window.localStorage.setItem(STORAGE_KEY, JSON.stringify(taskList));
}

//function that that edits tasks with date and time.
function editItem() { }

//function that that completes task.
function completeItem(event) {
    const element = event.target.closest(".task-content");
    let taskItem = element.querySelector(".new-task-created");
    let dateItem = element.querySelector(".due-date");
    let timeItem = element.querySelector(".due-time");
    // style..
    taskItem.style.textDecoration = "line-through";
    dateItem.style.textDecoration = "line-through";
    timeItem.style.textDecoration = "line-through";
}

I'd like to add that since completeItem function only changes the current DOM, it cannot be stored on localStorage so on refresh you won't know which tasks are completed. I would suggest adding a property completed to each taskList entry so you can recreate the completed state when refreshing.

as it was mentioned by Cristian the error that you are getting is because the function is not receiving the parameter ‘list’, you can simply try to put this instead:

function addTask() {
  display();
}

Then you should see the task on the UI but there are more things that you will need to improve related with your code logic

Related