Coding Feature.

JS) 바닐라 자바스크립트로 CRUD 구현. 맨 땅에 헤딩하기. 본문

Programming Language/JavaScript

JS) 바닐라 자바스크립트로 CRUD 구현. 맨 땅에 헤딩하기.

codingfeature 2023. 1. 11. 16:59

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>buttons</title>
        <link rel="stylesheet" href="style.css">
    </head>

    <body>
        <h1 id="main-title">Hello!</h1>
        <p><input type="text" id="inputs"></p>
        <p><input type="button" id="btn" value="submit"></p>
        <script type="text/javascript" src="script.js"></script>
    </body>
</html>
 
style.css
body{
    text-align: center;
}

 

And most importantly,

script.js

const title = document.getElementById("main-title");
const text = document.getElementById("inputs");
const btn = document.getElementById("btn");

function onClick(){
    title.innerHTML = text.value;
}

btn.addEventListener("click", onClick);

script.js

At first, by using the function getElementById()

제목을 표시할 곳(title),

텍스트를 입력할 곳(text),

버튼(btn) 변수에 element를 입력받는다.

 

그리고 btn에 EventListener를 적용시켜

버튼을 클릭할 때 마다 onClick이라는 사용자 정의 함수를 실행하도록 하였다.

 

onClick함수는 실행 시 title의 innerHTML을 사용해서 내용을 바꾸도록 한다.

그리고 text.value, 즉 텍스트창에 담긴 내용으로 바뀌도록 한다.

 

 

거기다 추가로 밤/낮 모드를 버튼으로 제어하는 기능을 추가해보았다.

const mainBody = document.getElementById("main-body");
function onClickChangeNightDay(){
    if(mainBody.className === 'day'){
        document.body.style.backgroundColor = "black";
        document.body.style.color = "white";
        mainBody.className = "night";
    } else{
        document.body.style.backgroundColor = "white";
        document.body.style.color = "black";
        mainBody.className = "day";      
    }
   
}

 

버튼을 클릭할 때 위와 같은 함수가 실행되는데,

body 태그에 main-body id를 설정해서 mainBody 에 element를 넣고,

mainBody.className을 통해 element 즉 body 태그의 클래스에 따라

낮과 밤이 바뀌는 기능을 추가했다.

 

 

제목이 바뀌는 대신,

리스트에 추가되는 방식으로 바꾸기로 했다.

 

        <ol id="lists">
            <li>Hello!
        </ol>

먼저 HTML 문서에 lists라는 id를 가진 ol 태그를 만들었다.

그 다음

const lists = document.getElementById("lists");

list element를 가져오고,

function onClick(){
    let li = document.createElement('li');
   
    li.innerHTML = text.value;
    lists.append(li);
}

함수를 위와 같이 수정하였다.

li 변수에 li 태그 element를 넣고,

li.innerHTML 의 내용을 텍스트 내용으로 만든 다음,

lists element에 새로운 내용인 li 변수를 append 하였다.

 

 

추가로 리스트를 가장 최근 내용부터 삭제하는 기능을 추가했다.

먼저 이전 list에 id를 차례대로 부여하였다.

function onClick(){
    let li = document.createElement('li');
   
    li.innerHTML = text.value;
    li.id = i;
    lists.append(li);

    i++;
}
 

그리고 아래 코드와 같이,

const btndelete = document.getElementById("btndelete");
 
function onClickDelete(){
    if(i === 1){
        alert('You don\'t have anything to delete!');
    }else{
        let lidelete = document.getElementById(i-1);
        lists.removeChild(lidelete);
        i--;
    }
}

lidelete에 가장 최근의 내용을 가진 element를 불러오고,

lists의 child로써 삭제한 뒤 i를 -1 하였다.

만약 리스트 내용이 없다면, 즉 i가 1이라면 (i는 이후 리스트가 받을 id이므로 실제 list 번호보다 1이 크다.)

경고문을 alert해주고 더 이상 진행되지 않도록 해준다.

 

 

 

그리고 클릭한 뒤 텍스트박스에 계속 쓴 글이 남아있는 것을 지우기 위해

function onClick(){
    let li = document.createElement('li');
   
    li.innerHTML = text.value;
    li.id = i;
    lists.append(li);

    text.value='';

    i++;
}

 위와 같이 text.value에 빈칸인 ''를 넣는 방식으로 구현하였다.

그리고 입력을 하지 않은 상태에서 submit 버튼을 누르면 경고문이 뜨도록 다음과 같이 코드를 추가하였다.

function onClick(){
    if(text.value===''){
        alert('Please write something!');
    }else{
        let li = document.createElement('li');
   
        li.innerHTML = text.value;
        li.id = i;
        lists.append(li);
   
        text.value='';
   
        i++;
    }
}

 

텍스트 박스를 하나 더 만들어서 담길 내용을 추가하였다.

그리고 listInside라는 배열을 추가하여

추가 내용을 저장하도록 하는 자료구조를 구현했다.

그래서 리스트 이름을 눌렀을 때 누른 리스트의 내용이

각 텍스트에 알맞게 나오도록 구현해보았다.

const textBig = document.getElementById("input-big");
var listInside = [];

listInside.push('temp');
function onClickList(event){
    text.value=event.target.innerHTML;
    textBig.value=listInside[event.target.id];
}
function onClick(){
    if(text.value===''){
        alert('Please write something!');
    }else{
        let li = document.createElement('li');
   
        li.innerHTML = text.value;
        listInside.push(textBig.value);

        li.id = i;
        li.addEventListener('click', onClickList);
        lists.append(li);
   
        text.value='';
        textBig.value='';
   
        i++;
    }
}

function onClickDelete(){
    if(i === 1){
        alert('You don\'t have anything to delete!');
    }else{
        let lidelete = document.getElementById(i-1);
        lists.removeChild(lidelete);
        listInside.pop();
        i--;
    }
}

위 코드를 보면,

temp라는 원소를 미리 listInside에 넣었는데,

이는 i가 1로 시작하는 것을 감안해서 listInside의 index를 1에서 시작하도록 하기 위해서이다.

리스트 명을 클릭하면 onClickList 함수가 실행되는데,

눌려진 리스트를 event.target으로 접근해서 innerHTML과 id를 구하고

id는 index로 사용해서 listInside에 접근하였다.

이로써 리스트 명과 거기에 담긴 내용을 다시 텍스트 창에 불러올 수 있었다.

 

입력 버튼을 누를 때마다 listInside 배열에 리스트 추가 내용을 집어넣는 push(),

그리고 다시 하나씩 원소를 제거하는 pop()을 사용하였다.

 

이로써 사용자는 리스트와 거기에 대한 추가 내용을 입력(Create), 열람(Read)할 수 있고,

LIFO 방식이지만 제거(Delete)도 가능하게 되었다.

이제 CRUD의 Update, 즉 수정 기능만 구현하면 된다.

 

수정 버튼을 만들고,

onClickUpdate 함수를 만들었다.

var clickedListId = -1;
 
function onClickList(event){
    text.value=event.target.innerHTML;
    textBig.value=listInside[event.target.id];

    clickedListId = event.target.id;
}
function onClickUpdate(){
    if(clickedListId == Number(-1)){
        alert('Please choose something on list to update!');
    }else if(text.value===''){
        alert('Please write something!');
    }else{
        templist = document.getElementById(clickedListId);
        templist.innerHTML = text.value;
        listInside[clickedListId] = textBig.value;
    }
}
 
여기서 clickedListId는 사용자가 클릭한 리스트의 ID 값을 저장하기 위한 용도로 사용되는 변수이다.
-1로 초기화했다.

onClickList 함수를 통해

event.target.id

즉 클릭한 ID를 받아들인다.

 

clickedListId가 -1일 때는 아직 사용자가 리스트를 누르지 않은 상태이므로

에러 메시지를 alert 처리 한다.

여기가 조금 까다로웠는데,

templist 라는 변수에다 clickedListId, 즉 누른 리스트의 ID 값을 가진 element를 집어넣고,

templist, 즉 누른 리스트 제목, 그리고 추가 내용을 innerHTML 그리고 listInside 배열을 통해

수정하였다.

 

이로써 CRUD 기능은 완성시켰다.

 

여기서 LIFO 형식으로 리스트 항목이 삭제되는 것을사용자가 선택한 항목을 삭제하는 것으로 기능을 수정해보았다.

function onClickDelete(){
    if(i === 1){
        alert('You don\'t have anything to delete!');
    }else{
        let lidelete = document.getElementById(clickedListId);
        document.getElementById('choice').textContent = lidelete.textContent+" delete!";
        lists.removeChild(lidelete);
        text.value='';
        textBig.value='';
    }
}

위 코드와 같이

lidelete 변수를 사용해 사용자가 누른 항목 element를 가져오고,

removeChild 함수로 삭제한다.

작동은 되지만 한 가지 결함이 존재하는데,

삭제를 해도 삭제된 항목의 추가 내용은 배열에 그대로 남아있는다는 점이다.

이로써 메모리 남용이 발생한다.