[포트폴리오 페이지]_13단계_CRUD 게시판 구현_(신규 데이터 Create)

2022. 4. 26. 13:11[Spring]_/[Spring]_포트폴리오 페이지 만들기

728x90
반응형

[환경]

 

개발툴 : IntelliJ

DB : oracle

프레임워크 : spring , mybatis

사용 언어 : ES6, Java , Html5 , CSS

 

완성 화면]

메뉴 1

 

등록 버튼 클릭시


개발 목표 : 기존에 만든 게시판에서 SPA 구현을 위해 등록기능 menu1 로 병합


https://yn971106.tistory.com/78

 

[포트폴리오 페이지]_10단계_CRUD 게시판 구현_(feat.등록기능 구현)

[환경] 개발툴 : IntelliJ DB : oracle 프레임워크 : spring , mybatis ---- 개발 목표 : 오라클 디비를 이용해서 게시판 CRUD 중 C(create) 만들기 [완료화면] 등록 버튼 클릭시 메뉴 1의 게시판에 새로운 항목..

yn971106.tistory.com

 

해당 포스트에서 검색기능 추가 및 쿼리 개선, 코드 개선을 한 부분을 정리하였습니다.

 

[ 메뉴 1 의 전체 소스코드 ]

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <style>
        .board {
            width: 100%;

        }
    </style>
</head>
<body>
<div id="content">
    <div id="contentwrap">
        <h2>CRUD</h2>
        <button class="regi">등록</button>
        <select id="selectview">
            <option value="10" selected="selected">10개씩 보기</option>
            <option value="15">15개씩 보기</option>
            <option value="20">20개씩 보기</option>
        </select>
        <select class="searchoption">
            <option value="titlename">제목</option>
            <option value="wirtername">작성자</option>
        </select>
        <input type="text" class="searchtext" value =""/>
        <button class="detailsearch">조회</button>
        <table border="1" class="board">
            <thead>
            <tr>
                <th>번호</th>
                <th>제목</th>
                <th>글쓴이</th>
                <th>작성일자</th>
                <th>조회수</th>
            </tr>
            </thead>
            <tbody id="table">
            </tbody>
            <!-- forEach 문은 리스트 객체 타입을 꺼낼때 많이 활용된다. -->
        </table>
        <span id="nav"></span>
    </div>
</div>
</body>
</html>
<script>
    $(document).ready(async function () {

        let regibtn = document.querySelector('.regi');
        let tbody = document.querySelector('#table');
        let viewcnt = document.querySelector('#selectview');
        let nav = document.querySelector('#nav');
        let $common = $commons.history

        let searchoption = document.querySelector('.searchoption');
        let searchtext = document.querySelector('.searchtext');
        let detailsearchbtn = document.querySelector('.detailsearch');




        searchtext.onkeyup = function(e){
            if(e.key === "Enter" || e.keyCode === 13 ){
                detailsearchbtn.click();
            }

        }

        viewcnt.onchange = function(){
            detailsearchbtn.click();
        }




        regibtn.onclick = function () {
            let url = "/regi/loader.do"
            let parentContent = document.querySelector('#contentwrap');
            let id = _commons().util.random();
            $common.sethistory(url,parentContent,id);
            let test = $common.gethistory(url);
            console.log(test);

            $('#content').load(url,function(){

            });

        }


        detailsearchbtn.onclick = function(){
            let wr;
            let ti;

            if(searchoption.value == "titlename" ){
                ti = searchtext.value;
                wr = "";
            }else{
                wr = searchtext.value;
                ti = "";
            }
            createBoard(1,wr,ti);
            createPagenation(wr,ti);
        }

        detailsearchbtn.click();

        async function createPagenation(wr,ti) {
            let cnt;

            while(nav.firstChild){
                nav.removeChild(nav.firstChild);
            }

            await fetch('/board/boardcount.do', {
                method: "POST",
                headers: {
                    'content-type': 'application/json'
                },
                body: JSON.stringify({
                    writer : wr,
                    title : ti
                })
            }).then(res => res.json())
                .then(data => {
                    cnt = data;
                })

            //총 페이지 수
            let totalpagecnt = Math.ceil(cnt / viewcnt.value);
            //페이지 숫자 생성.
            for (let i = 1; i <= totalpagecnt; i++) {
                //html 생성하기.
                let node = document.createElement('a');
                const template = `
                <a class="navclick" href="javascript:void(0)">\${i}</a>
                `
                node.innerHTML = template;

                node.querySelector('a').onclick = function () {
                    createBoard(i,wr,ti);

                }
                nav.appendChild(node);
            }

        }

        //테이블 생성
        async function createBoard(nowpage,wr,ti) {


            while(tbody.firstChild){
                tbody.removeChild(tbody.firstChild);
            }

            await fetch('/board/search.do', {
                method: "POST",
                headers: {
                    'content-type': 'application/json'
                },
                body: JSON.stringify({
                    view: viewcnt.value, // ~만큼 보기
                    pagenum: nowpage, // 페이지 숫자클릭넘버.
                    writer : wr,
                    title : ti
                })
            }).then(res => res.json())
                .then(data => {

                    for (let i = 0; i < data.length; i++) {

                        let node = document.createElement('tr');
                        const template = `
                                        <th><a href="javascript:void(0)" class="boardlink">\${data[i].NUM}</a></th>
                                        <th>\${data[i].title}</th>
                                        <th>\${data[i].writer}</th>
                                        <th>\${data[i].regdate}</th>
                                        <th>\${data[i].viewcnt}</th>
                                        `
                        node.innerHTML = template;
                        tbody.appendChild(node);

                        let boardlink = document.getElementsByClassName('boardlink');
                        boardlink[i].onclick =function(){
                            selectBoard(data[i].bno);
                        }
                    }

                });


            }

            //테이블 목록 클릭시 함수
            function selectBoard(bno){
                fetch('/board/selectboard.do',{
                    method:"POST",
                    headers: {
                        'content-type': 'application/json'
                    },
                    body :JSON.stringify({
                        bno: bno
                    })
                }).then(res => res.json())
                .then(data => {
                    console.log(data);
                    console.log(data[0].content);

                    let url = "/board/selectboarddetail.do"
                    let parentContent = document.querySelector('#contentwrap');
                    let id = _commons().util.random();
                    $common.sethistory(url,parentContent,id);

                    let jsondata = {
                        "title" : data[0].title,
                        "content" : data[0].content,
                        "writer" : data[0].writer,
                        "regdate" : data[0].regdate,
                        "bno" : data[0].bno
                    }

                    $('#content').load(url,jsondata,function(){

                    });
                })
            }




    });
</script>

 

1] 게시글 등록기능

regibtn.onclick = function () {
    let url = "/regi/loader.do"
    let parentContent = document.querySelector('#contentwrap');
    let id = _commons().util.random();
    $common.sethistory(url,parentContent,id);
    let test = $common.gethistory(url);
    console.log(test);

    $('#content').load(url,function(){

    });

}

등록 버튼 클릭시 전환할 화면 url 을 지정하고

등록 화면에서 뒤로가기 버튼 클릭시 이전의 화면을 다시 보여줘야 하기 때문에 이전에 만든 history 객체를 사용합니다.

 

히스토리 객체 생성은 다음 포스트 참고

https://yn971106.tistory.com/93

 

[포트폴리오 페이지]_12단계_SPA 구현을 위한 History 객체 만들기

[환경] 개발툴 : IntelliJ DB : oracle 프레임워크 : spring , mybatis 개발 목표 : 기존에 만든 게시판에서 SPA 을 유지하기 위해 common 파일 생성 common.js 파일을 사용할 위치를 지정해 줍니다. ( 자유 ) le..

yn971106.tistory.com

let $common = $commons.history

상단에 선언한 $common 변수로부터 원하는 함수를 찾아 사용 가능합니다.

 

저장할 element를 queryselector 를 이용해서 저장하고

이를 sethistory 를 이용해서 url을 key 값으로 element를 저장합니다.

 

그리고 나서 교체할 화면의 element를 선택하고 load 함수로 해당 url 요청으로 가져온 jsp 파일을

$ 선택자로 선택한 부분만 변경시킵니다.

 

1-2] Controller

@RequestMapping("/regi/loader.do")
public String regi() {
    return "/menu/boardregister";
}

단순히 화면 전환을 위한 jsp 의 위치를 반환합니다.

 

2] 등록 화면 jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

    <div id="contentwrap2">
    
            <input type="text" placeholder="제목" id="subject" name="subject">
            <input type="text" placeholder="내용" id="writecontent" name="content">
            <button type="button" class="reg">등록</button>
            <button type="button" class="backbtn">취소</button>
    </div>

</body>
</html>
<script src='/js/jquery-3.6.0.min.js?ver=1'></script>

<script>
    $(document).ready(function(){

        let title = document.querySelector('#subject');
        let content = document.querySelector('#writecontent');
        let $globalStorage = $commons.storage.g_variable;
        let writer = $globalStorage.getValue("loginUser");
        let date = $commons.util.date();
        let $common = $commons.history

        let backbtn = document.querySelector('.backbtn');
        let regibtn = document.querySelector('.reg');


        let changecontent =document.querySelector('#content');
        backbtn.onclick = function(){

            console.log('click back')
            let test = $common.gethistory("/regi/loader.do");
            console.log(test.content);
            // $('#content').load("/menu/menu1.do",function (){
            //
            // });

            let oldElement = document.querySelector('div#contentwrap2');
            changecontent.replaceChild(test.content,oldElement);

        };

        regibtn.onclick = function(){


            fetch("/board/register.do",{
                method: 'POST',
                headers: {
                    'content-type' : 'application/json'
                },
                body: JSON.stringify({
                    title: title.value,
                    content : content.value,
                    writer : writer,
                    regdate: date,
                    viewcnt : 0
                })
            }).then(res => res.json());

            $common.deletehistory("/regi/loader.do");

            let url = 'menu/menu1.do'
            $('#main_content').load(url,function(){

            });


        }

    });


</script>

해당 코드에서는 각각의 엘리먼트를 선언하고

이벤트를 달아줍니다.

 

2-1] 등록버튼 이벤트

regibtn.onclick = function(){


    fetch("/board/register.do",{
        method: 'POST',
        headers: {
            'content-type' : 'application/json'
        },
        body: JSON.stringify({
            title: title.value,
            content : content.value,
            writer : writer,
            regdate: date,
            viewcnt : 0
        })
    }).then(res => res.json());

    $common.deletehistory("/regi/loader.do");

    let url = 'menu/menu1.do'
    $('#main_content').load(url,function(){

    });


}

해당 코드에서 사용하는 선언문은

let title = document.querySelector('#subject');
let content = document.querySelector('#writecontent');
let $globalStorage = $commons.storage.g_variable;
let writer = $globalStorage.getValue("loginUser");
let date = $commons.util.date();
let regibtn = document.querySelector('.reg');

다음과 같습니다.

 

코드에서는 fetch 함수를 이용해서 쿼리를 던지고 전달 데이터는 html 에 입력된 값을 전달하게 됩니다.

전달할 값 중 writer 의 경우 현제 로그인한 계정 이름이 들어가야 하기 때문에.

Localstorage 에 저장된 유저정보를 가져오고 이를 전달합니다.

 

Localstorage 사용은 다음 포스트 참고

https://yn971106.tistory.com/54

 

[LocalStorage]_를 사용하여 값을 받거나 저장하기(feat. Spring)

목표] 위와 같이 textfield에 값 입력시 local 저장소에 저장이 되는 것을 해보았습니다. 우선 사용한 메소드를 알아보겠습니다. 값 저장하기] setItem(keyName, keyValue); window.localStorage.setItem(consta..

yn971106.tistory.com

 

통신에 성공하면 화면이 전환 될 것입니다.

※Controller - Service - Mapper 구조는 이전 포스트와 동일

https://yn971106.tistory.com/78

 

[포트폴리오 페이지]_10단계_CRUD 게시판 구현_(feat.등록기능 구현)

[환경] 개발툴 : IntelliJ DB : oracle 프레임워크 : spring , mybatis ---- 개발 목표 : 오라클 디비를 이용해서 게시판 CRUD 중 C(create) 만들기 [완료화면] 등록 버튼 클릭시 메뉴 1의 게시판에 새로운 항목..

yn971106.tistory.com

 

화면 전환시 등록된 게시글이 보여야 하고, 이는 갱신을 뜻합니다.

따라서 이전의 history를 가지고 있을 필요가 없으니. 이전에 저장한 url = key 값을 가진 객체를 삭제합니다.

그리고 content element 부분에 menu1을 다시 불러옵니다.

 

2-2] 취소버튼 이벤트

backbtn.onclick = function(){

    console.log('click back')
    let test = $common.gethistory("/regi/loader.do");
    console.log(test.content);
    // $('#content').load("/menu/menu1.do",function (){
    //
    // });

    let oldElement = document.querySelector('div#contentwrap2');
    changecontent.replaceChild(test.content,oldElement);

};

뒤로가기란 이전에 조회한 정보, 목록이 그대로 나와야 합니다. 따라서 등록페이지 진입 전에 저장한 history 객체의 content 부분을 가져오면 됩니다.

 

common 에 지정한 gethistory 함수를 이용해서 url 키를 가진 객체의 content 를 가져옵니다.

그리고 현제 있는 노드 -> oldElement 를 queryselector 로 지정하고

replaceChild 함수를 이용해서 서로를 교체합니다.

 

URL의 이동 없이 정상적으로 화면이 바뀌는 모습을 확인 할 수 있습니다.

감사합니다.

728x90
반응형