📌 to do list 만들기
본격적으로 졸업과제의 핵심인 to do list를 만들어보았다.
여러 가지 기능이 짬뽕되어 있어 한 번에 이해하기가 어려웠다.
그러니까 복습하는 거지만.
HTML
<form id="todo-form">
<input type="text" placeholder="Write a To Do and Press Enter" required />
</form>
<ul id="todo-list"></ul>
id가 todo-form이라는 form을 만들었고, 그 안에 input 타입이 text인 놈을 만든 후 밖에는 id가 todo-list인 ul을 만들었다.
JS
const toDoForm = document.getElementById("todo-form");
const toDoInput = document.querySelector("#todo-form input");
const toDoList = document.getElementById("todo-list");
function handleToDoSubmit(event) {
event.preventDefault();
const newTodo = toDoInput.value;
console.log(toDoInput.value);
toDoInput.value = "";
console.log(newTodo, toDoInput.value);
}
toDoForm.addEventListener("submit", handleToDoSubmit);
JS에서는 form과 input, list를 모두 잡아줬다.
이 form에 무언가가 제출될 때 handleToDoSubmit이라는 함수가 작동된다.
이 함수는 일단 제출할 때 디폴트인 새로고침을 방지해준다. (event라는 매개변수 적어주기)
이후 Input에 있는 value를 newTodo라는 변수에 저장해주고 리셋된 것처럼 블랭크를 보여주게 만든다.
저장한 이 값을 보여줄 수 있는 새로운 함수 paintToDo를 만든다.
function paintToDo(newTodo) {
const li = document.createElement("li");
const span = document.createElement("span");
li.appendChild(span);
span.innerText = newTodo;
toDoList.appendChild(li);
}
newTodo를 인수로 하는 paintToDo는 작동될 때마다 li와 span을 만든다.
li 밑에 span이 위치할 수 있게 appendChild를 해주고, span에 입력한 newTodo가 나오게 한다.
이 구조가 ul, toDoList 밑으로 들어간 형태다.
- newTodo
- newTodo1
ul > li > span > input값
이런 구조라고 이해했다.
그런데 문제는 새로고침을 하면 모두 리셋되고, 가장 큰 문제인 잘못 입력했을 때 삭제가 안된다는 것이다.
이 부분을 수정하기 위해 먼저 삭제하는 기능을 구현한다.
📌 to do list 삭제하기
function paintToDo(newTodo) {
const li = document.createElement("li");
const span = document.creatElement("span");
span.innerText = newTodo;
const button = document.creatElement("button");
button.innerText = "❎";
button.addEventListener("click", deleteToDo);
li.appendChild(span);
li.appendChild(button);
toDoList.appendChild(li);
}
JS에서 button을 만들어준다. 버튼 안에는❎ 이모지가 들어간다.
- 안녕 ❎
- 잘가 ❎
이런 형태라고 해야 하나. list 안에 span과 button이 들어 있고 span에는 입력한 to do 가 들어 있는 상태다.
저 이모지를 누르면 to do 가 삭제되게끔 deleteToDo라는 함수를 만든다.
근데 이모지를 눌러서 삭제를 하려고 하면 문제가 발생한다.
버튼이 클릭되는 건 알겠는데 내가 삭제하고 싶은 to do가 뭔지 컴퓨터가 이해하지 못한다는 것이다.
내가 삭제하고 싶은 to do 가 가진 값을 찾아본다.
우리는 버튼에 대한 정보, 그러니까 내가 누른 버튼에 대한 정보를 알면 내가 어떤 to do 를 삭제하고 싶은지를 알 수 있다.
이를 버튼에 대한, 부모 정보를 찾는다고 표현하는데 이벤트의 타겟(버튼 클릭)의 부모 요소를 찾으면 된다.
function deleteTodo(event) {
const li = event.target.parentElement;
li.remove();
}
deleteTodo는 클릭이 일어난 이벤트를 매개 변수로 하고 있으며, 이 이벤트 타겟의 부모 요소를 지우는 함수다.
내가 누른 버튼의 부모를 찾고, 그 부모 요소를 지워주는 것이다.
처음부터 이런 생각 나지 않고, 나중에도 이런 생각은 잘 나지 않는다.
그냥 이런 방법이 있구나 정도로 이해하고 넘어가면 좋겠다.
(니꼬샘... 도대체 이런 생각을 어떻게 하신건데요...)
O
o
📌 to do list 저장하기
삭제하기 전 문제가 하나 더 있었는데 바로 새로고침하면 적은 to do 가 모두 리셋된다는 거였다.
이걸 해결하기 위해 localStorage를 활용했다. (greeting 부분과 비슷한데 문제는 내가 그 부분에서 영혼이 나갔다는 것임)
먼저 toDo를 저장해야 한다.
이를 위해 toDos 라는 Array를 만들었다.
newTodo가 들어올 떄마다 이를 빈 Array에 추가하기 위해 toDos.push(newTodo) 라고 작성해주었다.
현재까지 to do 리스트를 입력하면 Array에 추가되는 형태까지 구현했다.
그러나 새로운 문제 (😭)localStorage는 Array를 저장할 수 없다는 것이다.이 놈은 문자열만 저장할 수 있어서, 우리는 JS에서 문자열로 변환시켜주는 JSON.stringify()를 사용했다.새로운 to do가 저장된 Array를 문자열로 바꿔준 후 localStorage에 저장했다.이제 이 저장된 내용이 화면에도 보이면 된다.
const TODOS_KEY = "todos";
function saveToDos() {
localStorage.setItem(TODOS_KEY, JSON.stringify(toDos));
}
화면에 보이게 하려면... 반대로 문자열이 Array로 변환되면 된다 ^^;이를 위해 JSON.parse() 를 사용한다. 이걸 사용하면 배열 형태(object 타입)으로 불러와 저장된다.이 배열 형태를 .forEach() 를 써서 배열 형태의 각 요소들을 출력시키면 된다.
const savedToDos = localStorage.getItem(TODOS_KEY);
if (savedToDos !== null) {
const parsedToDos = JSON.parse(savedToDos);
parsedToDos.forEach((item) => console.log("this is the turn of ", item));
}
saveToDos함수 안에는 localStorage에 저장된 놈들이 문자열 형태로 저장된다.
이놈들을 savedToDos라고 선언하고, 여기에 값이 있다면 이 문자열 형태를 배열 형태로 바꿔준다.
그렇게 바꾼 놈들(Array에 들어 있었던 것들)을 하나씩 꺼내주면 this is the turn of [안에 있던 놈] 이렇게 출력된다.
바꿨다 다시 바꿨다 난리 부르스 치는 중... ^^!
📌 to do list 저장하기2
네 아직 안 끝났읍니다... 기쁨도 잠시 또 다른 문제 발생 ㅎㅎ
새롭게 추가되는 게 아니라 자꾸 이전의 것을 덮어 씌우는 문제가 발생한다.
이는 우리가 처음에 Array를 설정할 때 const toDos = [] 로 설정했기 때문이었다.
이게 왜 문제냐면 newToDo를 작성해 submit할 때마다 빈 어레이에 푸시를 하게 되고,
새로운 toDo들만 포함하고 있는 어레이를 저장하기로 해놔서 전의 toDO는 갖고 있지 않게 된 것이다.
즉 어레이를 const가 아닌 let으로 바꾸어 업데이트가 가능하도록 바꿔주고,
localStorage에 toDos가 있으면 갖고 있는 toDo를 복원하게 만들어준다.
const savedToDos = localStorage.getItem(TODOS_KEY);
if (savedToDos !== null) {
const parsedToDos = JSON.parse(savedToDos);
toDos = parsedToDos;
parsedToDos.forEach(paintTodo);
}
대가리만 극지 말고 코딩을 해
...그거 어떻게 하는 건데...
이번 강의의 가장 큰 패착은 변수 이름이 다 비슷비슷해서 죽겠다는 것... ^^
📌 to do list 제대로 삭제하기
네 또 문제가 생겼음
to do를 지울 때마다 local storage에 업데이트가 되지 않는다......
아까 어떤 놈을 지우는지 지워는 지는데 로컬에는 업데이트가 안되는 것이에요...
function deleteToDo(event) {
const li = event.target.parentElement;
console.log(li.id);
li.remove();
}
function paintToDo(newTodo) {
const li = document.createElement("li");
li.id = newTodo.id;
const span = document.createElement("span");
span.innerText = newTodo.text;
const button = document.createElement("button");
button.innerText = "❌";
button.addEventListener("click", deleteToDo);
li.appendChild(span);
li.appendChild(button);
toDoList.appendChild(li);
}
function handleToDoSubmit(event) {
event.preventDefault();
const newTodo = toDoInput.value;
toDoInput.value = "";
const newTodoObj = {
text: newTodo,
id: Date.now(),
};
toDos.push(newTodoObj);
paintToDo(newTodoObj);
saveToDos();
}
if (savedToDos !== null) {
const parsedToDos = JSON.parse(savedToDos);
toDos = parsedToDos;
parsedToDos.forEach(paintToDo);
}
전체적으로 수정한 코드들...
그래서 이 to do 들에게 id를 주고, 로컬에서도 지우게끔 해준다. (li.id 와 remove 부분)
지우고 싶은 아이템만 빼고 새 어레이를 만드는 것이 삭제의 로직인데, 이를 위해 filter 함수를 사용한다.
function sexyFilter(item){return item !== 3 }
뭐 이런 식으로 이 필터는 item을 매개변수로, item이 3이 아니면 true를 리턴한다.
3이라면 필터에 걸려서 사라지는 구조다.
toDos = toDos.filter(toDo => toDo.id !== li.id);
내가 클릭한 li.id라면 필터에 걸려서 사라진다.
내가 클릭한 아이디가 아니면 남아 있는 것이다. (내가 삭제 버튼 안 누른 li는 남아 있는 형태)
몹시 힘들었다.............. ㅠ
아직도 마지막 부분은 잘 이해가 안된다.
어떻게 되긴 했고 어떻게 따라가긴 했는데 도저히 저런 생각이 나질 않음 :)
but... 일단 울면서 따라간다...
'👋🏻 JavaScript > 💭 노마드코더 바닐라JS' 카테고리의 다른 글
[노마드코더 바닐라JS로 그림 앱 만들기] #1 Canvas API (0) | 2023.03.21 |
---|---|
[노마드코더 바닐라JS로 크롬 앱 만들기] #8.0 ~ #8.2 (0) | 2023.03.10 |
[노마드코더 바닐라JS로 크롬 앱 만들기] #6.0 ~ #6.3 (0) | 2023.03.08 |
[노마드코더 바닐라JS로 크롬 앱 만들기] #5.0 ~ #5.3 (0) | 2023.03.08 |
[노마드코더 바닐라JS로 크롬 앱 만들기] #4.0 ~ #4.7 (0) | 2023.03.08 |