어제 만든 기능과 연관된 이슈들을 몇 가지 적어보려고 한다.
처음 innerhtml으로 데이터를 웹 상에 구현했을 때 여러 시도를 해보며 알게 된 점이 있다.
한 번은 innerhtml로 여러 태그들을 만들고 그 안에 데이터를 넣었다. 이를 이용해 그 만들어진 카드를 클릭하게 되면 이벤트가 발생하는 기능을 넣으려고 했다.
분명 alert을 띄워주는 eventListener를 넣어주었는데 alert이 뜨지 않았다.
그래서 처음에는 html 폴더에 없는 건(js만든 태그는) querySelector에 eventListener를 달 수 없다고 생각했다. 하지만 몇번의 시도 끝에 '만들어지고 난 다음에는 js로 만든 태그에 querySelector로 eventListener를 달아 사용할 수 있다' 라는 것을 깨달았다.
아마 나의 경우에는 div박스 안에 들어갈 내용과 기능들만 만들어두고 그 div박스를 어디에 위치할지 정해주지 않아 생긴 문제 같았다.
이를테면, 아래와 같이 div를 만들어 둔다 하더라도 div를 위치시킬 곳을 만들어 준 다음 선언해야 한다.
// div 생성하는 js 적혀있음
// ...
$movieCardList.appendChild($movieCard);
// 이후에 querySelector와 eventListener달기
마지막 과정으로는 검색 기능을 구현해야하는 과정이 있었다.
이 과정은 간단하게 두 가지로 나누어주어야겠다고 생각했다.
1. 기존의 div박스 지우기
2. 새로 필터링된 div 넣기
이렇게 구상을 한 뒤에 이 두개의 기능이 '검색'버튼을 누르면 한 번에 실행되게 filterMovieCard라는 함수안에 넣어주고 '검색'을 클릭했을 때 실행되도록 addeventListener의 콜백 함수로 넣어주었다.
div 지우기는 css 스타일의 display = "none"을 js로 넣어 진행했고 filtering은 데이터의 제목 안에 input입력값이 들어있는지 확인하는 조건을 넣어 조건이 맞는 경우만 리턴하도록 만들었다.
//버튼 누르면 input value 값으로 필터링하기.
const $inputBtn = document.querySelector('#inputBtn');
const $inputText = document.getElementById('inputText');
// onsubmit 무조건 submit하게 만들어 줌.
function trueFunc(event) {
event.preventDefault();
return true;
}
// 클릭, 엔터 이벤트
$inputBtn.addEventListener('click', filterMovieCard);
$inputText.addEventListener('keyup', (event) => {
let key = event.key || event.keyCode;
if (key == 13) {
$inputBtn.click();
}
});
function filterMovieCard() {
// 기존 div hide
const movieCards = document.querySelectorAll('.movieCard');
movieCards.forEach((movieCard) => {
movieCard.style.display = "none";
});
fetch(
"https://api.themoviedb.org/3/movie/top_rated?language=en-US&page=1",
options
)
.then((response) => response.json())
.then((data) => {
const $movieCardList = document.querySelector(".cardContainer");
// filtering
const filteredVal = data.results.filter((movie) => {
return movie.title.toLowerCase().includes($inputText.value.toLowerCase());
})
filteredVal.forEach((movie) => {
const $movieCard = document.createElement("div");
$movieCard.className = "movieCard";
$movieCard.innerHTML = `
<img src="https://image.tmdb.org/t/p/w500${movie.poster_path}" alt="${movie.title}">
<h3>${movie.title}</h3>
<p>${movie.overview}</p>
<p>rating : ${movie.vote_average}</p>`;
$movieCardList.appendChild($movieCard);
// 카드 클릭시 alert 띄우기
$movieCard.addEventListener('click', printID);
function printID() {
alert(`영화 id: ${movie.id}`);
};
})
})
.catch((err) => console.error(err));
}
div 지우기, filtering과 검색까지 모두 마치고 검색버튼을 누르면 클릭되도록 만들었다.
하지만 click만으로는 만족스럽지 못했다. 나도 네이버 검색창에 검색할 땐 클릭보단 엔터를 많이치는걸...
그래서 엔터도 넣기로 했다. 클릭하거나 입력했을 때 작동할 함수는 이미 만들어뒀기 때문에 이벤트리스너만 달아주면 끝이었다.(끝이라고 생각했다...)
// onsubmit 무조건 submit하게 만들어 줌.
function trueFunc(event) {
event.preventDefault();
return true;
}
// 클릭, 엔터 이벤트
$inputBtn.addEventListener('click', filterMovieCard);
$inputText.addEventListener('keyup', (event) => {
let key = event.key || event.keyCode;
if (key == 13) {
$inputBtn.click();
}
엔터키로 인해 추가된 부분은 대강 위와 같다.
여기서 문제가 몇 가지 발생했다. 일단 엔터키를 눌렀을 때 그 키를 인식할 수 있게 key를 가져와야 하는데 처음엔 keycode로 key를 가져온 뒤에 key===13(엔터키 번호) 를 넣었더니 작동되지 않았다.
이에 대한 문제를 찾아보니 keycode는 호환되지 않는 브라우저가 있을 수도 있다고,,, 따라서 event.key를 가져와야 한다길래 or연산자를 이용해 둘 중 truthy한 값이 key값으로 들어가도록 설정해주었다.
그런데 여기서 문제가 하나 더 발생하는데 분명 클릭시와 똑같이!! 되어있지만 이벤트가 발생하지 않는다!!!!
이에 대해서 주변의 도움을 구했다.내가 html 폴더에 form안에 검색창을 넣어놨는데 form을 쓰는 이유는 따로 있다고 하더라. form의 속성으로 onsubmit = "함수"를 가질 수 있는데 이 함수의 결과값이 true이면 무조건 submit 하게 만들 수 있다. 따라서 onsubmit속성값을 쓰고 그 안에 있는 함수에 return true값을 넣어주면서 무조건 submit 될 수 있게 했더니 똑바로 동작하게 되었다.
그렇다면 지금까진 submit이 되지 않았다는건데 왜 click은 왜 잘만된거지...?(submit값이 아니라 input text안의 값이 ~이면 클릭했을 때 그 값을 기준으로 비교하도록 만들어놓아서 그런건가)
아무튼 이 부분은 튜터님께 질문드리도록 해야겠다.!!
'TIL' 카테고리의 다른 글
2023_10_23 TIL (0) | 2023.10.23 |
---|---|
2023_10_20 TIL (0) | 2023.10.23 |
2023_10_18 TIL (1) | 2023.10.23 |
2023_10_17 TIL (0) | 2023.10.19 |
2023_10_16 TIL (2) | 2023.10.18 |