Todo 수정,삭제,완료

나야나·2022년 7월 1일
0
post-thumbnail

TodoList에서 내용을 변경, 삭제, 완료기능을 추가했다.
영상은 처음 찍어보는 거라서 크기 조절이나 이런부분이 미흡하다...

삭제, 완료기능은 해당 버튼을 클릭시 해당함수로 넘어가도록 설정했지만 변경부분은 바로 넘어가는 것이 아닌 더블클릭으로 진행됐을때 기존 value값을 보여주고 변경할 수 있도록 진행했다.
기능 모두 todo의 id값을 매개변수로 넘겨줘서 값을 비교해 일치하는 값이 변경되도록 했다.

const paintTodos = function (todo) {
 
  todoItems.forEach((todo) => {
    const li = document.createElement("li");
    li.classList.add("todo_item");
    const checkBox = document.createElement("div");
    const div = document.createElement("div");
    const button = document.createElement("button");
    checkBox.classList.add("todo_check");
    div.classList.add("todo_text");
    button.classList.add("todo_delete");

    div.innerText = todo.content;
    button.innerHTML = '<i class="fa-solid fa-x"></i>';

    // Delete
    button.addEventListener("click", () => todoDelete(todo.id));

    // Completed;
    checkBox.addEventListener("click", (e) => todoCompleted(e, todo.id));

    if (todo.completed) {
      checkBox.classList.add("checked");
      checkBox.innerHTML = '<i class="fa-solid fa-check" id="check"></i>';
      div.style.textDecoration = "line-through";
      div.style.color = "gray";
    }
    todoList.appendChild(li);
    li.appendChild(checkBox);
    li.appendChild(div);
    li.appendChild(button);
    li.setAttribute("id", todo.id);
    // update 전 todo value 값 받는 곳
    div.addEventListener("dblclick", (e) => todoDblclick(e));
    // });
};

Delete 구현

filter 함수를 이용하여 id가 일치하지 않는 todo만 뽑아 새로운 배열을 만들어 기존 todos에 담았다.
그리고 todos를 paintTodo() 함수를 통해 todos를 forEach 함수를 이용하여 보여준다.

function todoDelete(todoId) {
  const _todos = todos.filter((todo) => {
    return todo.id !== todoId;
  });
  todos = _todos;
  paintTodo(todos);
  saveTodo();
}

completed 구현

Delete와 마찬가지로 todoId를 매개변수로 받아와 비교하지만, map을 이용하여 todo의 id가 같은 값을 찾아 일치하면 전개연산자를 이용하여 체크박스의 클릭여부에 따라 completed 값을 true, false로 변화시켜 _todos에 담고, 그 배열을 todos에 저장한다.
그리고 todos를 paintTodo() 함수를 통해 todos를 forEach 함수를 이용하여 보여준다.

function todoCompleted(todoId) {
  const _todos = todos.map((todo) => {
    return todo.id == todoId ? { ...todo, completed: !todo.completed } : todo;
  });
  todos = _todos;
  paintTodo(todos);
  saveTodo();
}

Dblclick 구현

li안에 div들로 이루어져 있기 때문에 div가 클릭됐을때 li안에 요소를 input으로 변화시키고 싶었다.
그래서 target의 부모요소를 가져와 innerHTML를 비우고 input을 생성하여 추가해줬다.
클릭된 값의 value는 innerText로 저장되어 있기 때문에 그 값은 setAttribute를 통하여 input의 value로 설정해준다.
그 뒤에 enter를 누르면 todoUpdate() 함수가 실행된다.

function todoDblclick(e) {
  const text = e.target;
  const li = text.parentElement;
  li.innerHTML = null;
  const input = document.createElement("input");
  li.appendChild(input); // input을 li요소 안에 추가
  const inputText = text.innerText;
  input.setAttribute("value", inputText);
  const todoId = li.id;
  li.addEventListener("keyup", () => todoUpdate( todoId));
}

update 구현

input의 값이 변화가 되고 Enter를 누르면 변화가 된 값을 v변수로 받아 map함수를 사용하여 id를 비교하여 일치한다면 content의 값이 변화되도록 하였다. 그리고 마찬가지로 todos에 담았다.

function todoUpdate(todoId) {
  if (e.keyCode === 13) {
    const value = e.target.value;
    const _todos = todos.map((todo) => {
      return todo.id == todoId ? { ...todo, content: value } : todo;
    });
    todos = _todos;
    paintTodo(todos);
    saveTodo();
  }
}

일단 기본적인 CRUD는 이것으로 완료다.

다음은 달력을 만드는 것에 대해 작성해야겠다!

문제점 모음

문제점 1
  • 나는 사실 일치하지 않는 것을 return 한다는게 이해가 잘 가지 않았었는데, filter라는 함수에 대해 이해가 완벽하지 않아 문제가 발생했던 것이였다.
    filter 함수는 조건이 일치하는 새로운 배열을 만들어낸다.
    Delete를 구현할때 filter를 이용했던 이유는 클릭된 todo는 제외된 todo 배열이 필요하기 때문이였다!

문제점 2

  • 이 기능들을 구현할 때 id값을 비교하는 것에서 문제가 발생했다. === 는 type까지 일치해야 true / == 는 type은 비교하지 않고 값이 일치하면 true 이다.
    todo.id는 숫자로 저장이 됐지만, 매개변수로 받아온 todoId는 문자열로 보여지기 때문에 그런 문제가 발생한 것이라고 생각한다. 결론적으로는 type까지 비교하지 않도록 ==를 사용하여 해결했지만.. TypeScript를 사용해보고 싶은 마음이 조금은 생긴 순간이였다..ㅎ
profile
열심히 하는 중

0개의 댓글