https://bobo12.tistory.com/312
4. 화면에서 검색 조건 처리
▷ 페이지 번호가 파라미터로 유지되었던 것처럼 검색 조건과 키워드 역시 항상 화면 이동 시 같이 전송되어야 함
▷ 화면에서 검색 버튼을 클릭하면 새로 검색을 한다는 의미이므로 1페이지로 이동
▷ 한글의 경우 GET 방식으로 이동하는 경우 문제가 생길 수 있으므로 주의
(1) 목록 화면에서 검색 처리
◎ llist.jsp 수정(테이블 밑에 search 내용 추가)
<div class='row'> <div class="col-lg-12"> <form id='searchForm' action="/board/list" method='get'> <select name='type'> <option value="">--</option> <option value="T">제목</option> <option value="C">내용</option> <option value="W">작성자</option> <option value="TC">제목 or 내용</option> <option value="TW">제목 or 작성자</option> <option value="TWC">제목 or 내용 or 작성자</option> </select> <input type='text' name='keyword' /> <input type='hidden' name='pageNum' value='${pageMaker.cri.pageNum}'> <input type='hidden' name='amount' value='${pageMaker.cri.amount}'> <button class='btn btn-default'>Search</button> </form> </div> </div>
http://localhost:8080/board/list 에서 검색하면 아래와 같은 창이 출력되며 검색 기능도 적용 됩니다.
▷ Chrome 브라우저는 한글로 검색하는 경우 주소창에는 한글이 깨지지 않음
▷ 실제로는 그림에 있는 박스의 내용물 처럼 전송됨
▶ 3페이지를 보다가 검색하면 3페이지로 이동하는 문제
▶ 검색 후 페이지를 이동하면 검색 조건이 사라지는 문제
▶ 검색 후 화면에서는 어떤 검색 조건과 키워드를 이용했는지 알 수 없는 문제들이 있음
◎ 검색 버튼의 이벤트 처리
▷ 검색 버튼을 클릭하면 검색은 1페이지를 하도록 수정하고, 화면에 검색 조건과 키워드가 보이게 처리하는 작업 우선 진행
◎ list.jsp 수정 (검색 버튼 이벤트 처리)
var searchForm = $("#searchForm"); $("#searchForm button").on("click", function(e) { if(!searchForm.find("option:selected").val()) { alert("검색종류를 선택하세요"); return false; } if(!searchForm.find("input[name='keyword']").val()) { alert("키워드를 입력하세요"); return false; } searchForm.find("input[name='pageNum']").val("1"); e.preventDefault(); searchForm.submit(); });
▷ 윗 부분은 자바스크립트의 내용을 수정한 것
▷ 브라우저에서 검색 버튼을 클릭하면 <form> 태그의 전송은 막고, 페이지 번호는 1이 되도록 처리
▷ 화면에서 키워드가 없다면 검색하지 않도록 제어
◎ select 태그, input 태그 내용 수정
▷ 검색 후 주소창에서 검색 조건과 키워드가 같이 GET 방식으로 처리되므로 내용 수정<form id='searchForm' action="/board/list" method='get'> <select name='type'> <!-- <option value="">--</option> <option value="T">제목</option> <option value="C">내용</option> <option value="W">작성자</option> <option value="TC">제목 or 내용</option> <option value="TW">제목 or 작성자</option> <option value="TWC">제목 or 내용 or 작성자</option> --> <option value="" <c:out value="${pageMaker.cri.type == null ? 'selected' : '' }"/>> --</option> <option value="T" <c:out value="${pageMaker.cri.type eq 'T' ? 'selected' : '' }"/>> 제목</option> <option value="C" <c:out value="${pageMaker.cri.type eq 'C' ? 'selected' : '' }"/>> 내용</option> <option value="W" <c:out value="${pageMaker.cri.type eq 'W' ? 'selected' : '' }"/>> 작성자</option> <option value="TC" <c:out value="${pageMaker.cri.type eq 'TC' ? 'selected' : '' }"/>> 제목 or 내용</option> <option value="TW" <c:out value="${pageMaker.cri.type eq 'TW' ? 'selected' : '' }"/>> 제목 or 작성자</option> <option value="TWC" <c:out value="${pageMaker.cri.type eq 'TWC' ? 'selected' : '' }"/>> 제목 or 내용 or 작성자</option> </select> <input type='text' name='keyword' value='<c:out value="${pageMaker.cri.keyword}"/>' /> <input type='hidden' name='pageNum' value='<c:out value="${pageMaker.cri.pageNum}"/>' /> <input type='hidden' name='amount' value='<c:out value="${pageMaker.cri.amount}"/>' /> <button class='btn btn-default'>Search</button> </form>
▷ select 태그의 내부는 삼항 연산자를 이용해 해당 조건으로 검색되었다면 selected라는 문자열을 출력하게 해서 화면에서 선택된 항목으로 보이도록 합니다.
◎ 출력 결과
(1) 검색 항목이 선택되지 않은 경우
(2) 키워드를 입력하지 않은 경우
(3) 검색시는 무조건 1페이지로
▷ 검색시 무조건 1페이지로 넘어가고 검색했던 조건들도 그대로 남아있습니다.
◎ form 태그 수정<form id='actionForm' action="/board/list" method='get'> <input type='hidden' name='pageNum' value='${pageMaker.cri.pageNum}'> <input type='hidden' name='amount' value='${pageMaker.cri.amount}'> <input type='hidden' name='type' value='<c:out value="${pageMaker.cri.type }"/>'> <input type='hidden' name='keyword' value='<c:out value="${pageMaker.cri.keyword }"/>'> </form>
▷ 검색 조건과 키워드에 대한 처리가 되면 검색 후 페이지를 이동해도 동일한 검색 사항들이 계속 유지됨
(2) 조회 페이지에서 검색 처리
▷ 목록 페이지에서 조회 페이지로의 이동은 이미 <form> 태그를 이용해 처리했기 때문에 별도의 처리가 필요 없음
▷ 조회 페이지는 아직 Criteria의 type과 keyword에 대한 처리가 없기 때문에 이 부분을 수정해 줄 필요가 있음
◎ src/main/webapp/WEB-INF/views/board → get.jsp 수정
<form id='operForm' action="/board/modify" method="get"> <input type='hidden' id='bno' name='bno' value='<c:out value="${board.bno}"/>'> <input type='hidden' name='pageNum' value='<c:out value="${cri.pageNum}"/>'> <input type='hidden' name='amount' value='<c:out value="${cri.amount}"/>'> <input type='hidden' name='keyword' value='<c:out value="${cri.keyword}"/>'> <input type='hidden' name='type' value='<c:out value="${cri.type}"/>'> </form>
(3) 수정/삭제 페이지에서 검색 처리
▷ 조회 페이지에서 수정/삭제 페이지로의 이동은 GET 방식을 통해서 이동하고, 이동 방식 역시 <form> 태그 이용
▷ 기존의 <form> 태그에 추가적인 type과 keyword 조건만을 추가
◎ src/main/webapp/WEB-INF/views/board → modify.jsp 수정
<form role="form" action="/board/modify" method="post"> <input type='hidden' name='pageNum' value='<c:out value="${cri.pageNum }"/>'> <input type='hidden' name='amount' value='<c:out value="${cri.amount }"/>'> <input type='hidden' name='type' value='<c:out value="${cri.type }"/>'> <input type='hidden' name='keyword' value='<c:out value="${cri.keyword }"/>'>
◎ src/main/java/org.codehows.controller → BoardController 수정
▷ 수정/삭제 처리는 BoardController에서 redirect 방식으로 동작하므로 type과 keyword 조건을 같이 리다이렉트시 포함
@PostMapping("/modify") public String modify(BoardVO board, @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) { log.info("modify: " + board); if (service.modify(board)) { rttr.addFlashAttribute("result", "success"); } rttr.addAttribute("pageNum", cri.getPageNum()); rttr.addAttribute("amount", cri.getAmount()); rttr.addAttribute("type", cri.getType()); rttr.addAttribute("keyword", cri.getKeyword()); return "redirect:/board/list"; } @PostMapping("/remove") public String remove(@RequestParam("bno") Long bno, @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) { log.info("remove..........." + bno); if (service.remove(bno)) { rttr.addFlashAttribute("result", "success"); } rttr.addAttribute("pageNum", cri.getPageNum()); rttr.addAttribute("amount", cri.getAmount()); rttr.addAttribute("type", cri.getType()); rttr.addAttribute("keyword", cri.getKeyword()); return "redirect:/board/list"; }
▷ 리다이렉트는 get 방식으로 이루어지기 때문에 추가적인 파라미터를 처리해야 함
◎ src/main/webapp/WEB-INF/views/board → modify.jsp 수정
▷ 다시 목록으로 이동하는 경우에 필요한 파라미터만 전송하기 위해 form 태그의 모든 내용을 지우고 다시 추가하는 방식 사용
▷ keyword, type 역시 추가하도록 아래와 같이 관련된 JavaScript 코드를 수정해야 함
<script type="text/javascript"> $(document).ready(function() { var formObj = $("form"); $('button').on("click", function(e){ e.preventDefault(); var operation = $(this).data("oper"); console.log(operation); if(operation === 'remove'){ formObj.attr("action", "/board/remove"); }else if(operation === 'list'){ //move to list formObj.attr("action", "/board/list").attr("method","get"); var pageNumTag = $("input[name='pageNum']").clone(); var amountTag = $("input[name='amount']").clone(); var keywordTag = $("input[name='keyword']").clone(); var typeTag = $("input[name='type']").clone(); formObj.empty(); formObj.append(pageNumTag); formObj.append(amountTag); formObj.append(keywordTag); formObj.append(typeTag); } formObj.submit(); }); }); </script>
수정/조회 화면에서 어떤 작업을 하던지 다시 목록 페이지로 검색 조건이 유지되는지 확인해야 함
http://localhost:8080/board/list
위의 경로로 접속 시 아래와 같은 화면이 나타나고 수정/조회를 한 이후에도 다시 목록 페이지로 검색 조건이 유지됩니다.
◎ UriComponentsBuilder를 이용하는 링크 생성
▷ 웹페이지에서 매번 파라미터를 유지하는 일이 번거롭다면 UriComponentsBuilder 클래스 이용
▷ 여러 개의 파라미터들을 연결해서 URL의 형태로 만들어주는 기능을 가지고 있음
◎ Criteria 클래스 내용 추가
▷ URL을 만들어주면 리다이렉트 하거나, <form> 태그를 사용하는 상황을 많이 줄여주며 링크 생성 기능 추가
public String getListLink() { UriComponentsBuilder builder = UriComponentsBuilder.fromPath("") .queryParam("pageNum", this.pageNum) .queryParam("amount", this.getAmount()) .queryParam("type", this.getType()) .queryParam("keyword", this.getKeyword()); return builder.toUriString(); }
queryParam()이라는 메소드를 이용해 필요한 파라미터들을 손쉽게 추가할 수 있음Criteria cri = new Criteria(); cri.setPageNum(3); cri.setAmount(20); cri.setKeyword("새로"); cri.setType("TC");
위와 같은 조건들로 Criteria가 생성된다면 getListLink()의 결과는 get 방식에 적합한 URL 인코딩 결과로 만들어짐
(가장 편리한 점은 한글 처리에 신경 쓰지 않아도 된다는 점)
◎ src/main/java/org.codehows.controller → BoardController 수정
@PostMapping("/modify") public String modify(BoardVO board, @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) { log.info("modify: " + board); if(service.modify(board)) { rttr.addFlashAttribute("result", "success"); } /* rttr.addAttribute("pageNum", cri.getPageNum()); rttr.addAttribute("amount", cri.getAmount()); rttr.addAttribute("type", cri.getType()); rttr.addAttribute("keyword", cri.getKeyword()); */ return "redirect:/board/list" + cri.getListLink(); } @PostMapping("/remove") public String remove(@RequestParam("bno") Long bno, @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) { log.info("remove..........." + bno); if(service.remove(bno)) { rttr.addFlashAttribute("result", "success"); } /* rttr.addAttribute("pageNum", cri.getPageNum()); rttr.addAttribute("amount", cri.getAmount()); rttr.addAttribute("type", cri.getType()); rttr.addAttribute("keyword", cri.getKeyword()); */ return "redirect:/board/list" + cri.getListLink(); }
▷ UriComponentsBuilder로 생성된 URL은 화면에서도 유용하게 사용될 수 있는데,
▷ 주로 JavaScript를 사용할 수 없는 상황에서 링크를 처리해야 하는 상황에서 사용 됨
목록 페이지나 수정/삭제 페이지들을 script나 BoardController, jsp의 내용을 수정함으로써 모든 기능들을 사용했을 시 검색 조건이 그대로 남아 있는 것을 확인할 수 있었습니다.
이렇게 검색까지 가능하도록 홈페이지를 구현해보았습니다!
다음은 REST에 대해서 배워볼게요~!!
많은 분들의 피드백은 언제나 환영합니다! 많은 댓글 부탁드려요~~
![](https://t1.daumcdn.net/keditor/emoticon/friends1/large/002.gif)
'BackEnd > Spring' 카테고리의 다른 글
[코드로 배우는 스프링 웹 프로젝트] ch16 REST 방식으로 전환 2(JSON, XML, 객체 반환, ResponseEntity) (0) | 2023.03.31 |
---|---|
[코드로 배우는 스프링 웹 프로젝트] ch16 REST 방식으로 전환 1(@RestController) (0) | 2023.03.31 |
[코드로 배우는 스프링 웹 프로젝트] ch15 검색 처리 1(sql, MyBatis 동적 태그) (0) | 2023.03.31 |
[코드로 배우는 스프링 웹 프로젝트] ch14 페이징 화면 처리 2(script, get, modify) (0) | 2023.03.31 |
[코드로 배우는 스프링 웹 프로젝트] ch14 페이징 화면 처리 1(startPage, endPage) (0) | 2023.03.31 |