-
스프링 - 항목 추가를 했을때 처리 방법카테고리 없음 2021. 11. 20.반응형
데이터를 넘길때 입력폼이 고정된 한개면 넘기는건 쉽다
하지만 학력사항 추가, 자격증 추가 등 HTML의 항목들을 사용자가 임의로 여러개 추가를한다면
그 추가된 값들을 넘기는건 고정된 하나를 넘기는것과 많이 다르다.
아이디 패스워드 이름을 넘기는건 쉽다.
하지만 추가된 학력사항, 자격등 등을 넘기는건 어렵다.
<%@ page contentType="text/html; charset=UTF-8"%> <%@ page trimDirectiveWhitespaces="true" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <link rel="icon" href="data:;base64,iVBORw0KGgo="> <style type="text/css"> *{ margin: 0; padding: 0; box-sizing: border-box; } body { font-size: 14px; font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif; } a { color: #000; text-decoration: none; cursor: pointer; } a:active, a:hover { text-decoration: underline; color: #F28011; } .btn { color: #333; border: 1px solid #333; background-color: #fff; padding: 4px 10px; border-radius: 4px; font-weight: 500; cursor:pointer; font-size: 14px; font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif; vertical-align: baseline; /* 부모 요소의 기준선에 맞춤 */ } .btn:hover, .btn:active, .btn:focus { background-color: #e6e6e6; border-color: #adadad; color:#333; } .btn[disabled], fieldset[disabled] .btn { pointer-events: none; cursor: not-allowed; filter: alpha(opacity=65); -webkit-box-shadow: none; box-shadow: none; opacity: .65; } .boxTF { border: 1px solid #999; padding: 5px 5px; background-color: #fff; border-radius: 4px; font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif; vertical-align: baseline; } .selectField { border: 1px solid #999; padding: 4px 5px; border-radius: 4px; font-family: "맑은 고딕", 나눔고딕, 돋움, sans-serif; vertical-align: baseline; } textarea:focus, input:focus { outline: none; } .body-title { width:100%; height:45px; line-height:45px; text-align:left; font-weight: bold; font-size:15px; } .body-container{ width:800px; min-height: 500px; margin: 30px auto 10px; } .member-form .input-session{ margin-bottom: 15px; } .member-form .input-title{ font-size:13px; color: #212121; line-height: 180%; } .member-form .input-title{ font-size:14px; color: #212121; } .member-form .input-box{ border: 1px solid #A6A6A6; padding: 10px 10px; clear: both; } .member-form .input-box p{ padding: 3px 0; } .member-form .input-box label{ display:inline-block; width: 110px; } .member-form .input-box span{ display: inline-block; } .member-form .member-confirm{ line-height: 150%; text-align: center; } .schoolRemoveBtn, .licenseRemoveBtn { cursor: pointer; display: inline-block; width: 40px; text-align: center; } </style> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css"> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script type="text/javascript"> $(function(){ $(".schoolRemoveBtn").hide(); $(".licenseRemoveBtn").hide(); $(".schoolAddBtn").click(function(){ $(".schoolRemoveBtn").show(); var p=$(this).parent().parent().find("div:first-child :first").clone(); $(p).find("input").each(function(){ $(this).val(""); }); $(this).parent().parent().find("div:first").append(p); }); $("body").on("click", ".schoolRemoveBtn", function(){ if($(this).closest("div").find("p").length<=1) { // closest("태그") : 가장가까운 부모태그 return; } $(this).parent().remove(); if($(".schoolRemoveBtn").closest("div").find("p").length<=1) { $(".schoolRemoveBtn").hide(); } }); }); $(function(){ $(".licenseAddBtn").click(function(){ $(".licenseRemoveBtn").show(); var p=$(this).parent().parent().find("div:first-child :first").clone().wrapAll("<div>").parent().html(); $(p).find("input").each(function(){ $(this).val(""); }); $(this).parent().parent().find("div:first").append(p); }); $("body").on("click", ".licenseRemoveBtn", function(){ if($(this).closest("div").find("p").length<=1) { return; } $(this).parent().remove(); if($(".licenseRemoveBtn").closest("div").find("p").length<=1) { $(".licenseRemoveBtn").hide(); } }); }); function sendOk() { var f = document.memberForm; var str; str = f.userId.value; if( !/^[a-z][a-z0-9_]{4,9}$/i.test(str) ) { alert("아이디는 5~10자이며 첫글자는 영문자이어야 합니다."); f.userId.focus(); return; } str = f.userPwd.value; if( !/^(?=.*[a-z])(?=.*[!@#$%^*+=-]|.*[0-9]).{5,10}$/i.test(str) ) { alert("패스워드는 5~10자이며 하나 이상의 숫자나 특수문자가 포함되어야 합니다."); f.userPwd.focus(); return; } str = f.userName.value; if( !str ) { alert("이름을 입력하세요. "); f.userName.focus(); return; } var b; b = true; $("input[name=schoolName]").each(function(index){ if(! $(this).val()) { b = false; } if(! b) return false; if(! $("input[name=schoolDate1]").eq(index).val()) { b = false; } if(! b) return false; if(! $("input[name=schoolDate2]").eq(index).val()) { b = false; } if(! b) return false; }); if(! b) { alert("학력사항을 정확히 입력 하세요"); return; } b = true; $("input[name=licenseName]").each(function(index){ if(! $(this).val()) { $("input[name=licenseDate]").eq(index).val(""); return false; } if(! $("input[name=licenseDate]").eq(index).val()) { b = false; } if(! b) return false; }); if(! b) { alert("자격증 정보를 입력 하세요"); return; } // 입력하지 않은 자격증 컨트롤 지우기 $("input[name=licenseName]").each(function(index){ if(! $(this).val()) { $(this).closest("p").remove(); } }); f.action = "${pageContext.request.contextPath}/member/signup"; f.submit(); } </script> </head> <body> <div class="body-container"> <div class="body-title"> <h3><span><i class="far fa-address-card"></i></span> 회원가입 </h3> </div> <div class="body-container"> <form name="memberForm" method="post"> <div class="member-form"> <div class="input-session basic-input"> <div class="input-title"><h4>기본 입력 사항</h4></div> <div class="input-box"> <p> <label>아이디 : </label> <input type="text" name="userId" class="boxTF" style="width: 82%;" placeholder="아이디 입력"> </p> <p> <label>패스워드 :</label> <input type="password" name="userPwd" class="boxTF" style="width: 82%;" placeholder="패스워드 입력"> </p> <p> <label>이름 :</label> <input type="text" name="userName" class="boxTF" style="width: 82%;" placeholder="이름 입력"> </p> </div> </div> <div class="input-session education-input"> <div class="input-title"><h4>학력 사항</h4></div> <div class="input-box"> <div> <p> <input type="text" name="schoolName" class="boxTF" style="width: 27%;" placeholder="학교명을 입력하세요"> <input type="date" name="schoolDate1" class="boxTF" style="width: 27%;" placeholder="입학날짜를 입력하세요"> ~ <input type="date" name="schoolDate2" class="boxTF" style="width: 27%;" placeholder="졸업날짜를 입력하세요"> <span class="schoolRemoveBtn" style="float: right;"><i class="far fa-minus-square"></i></span> </p> </div> <div style="text-align: center; margin-top: 10px;"> <button type="button" class="btn schoolAddBtn">추가</button> </div> </div> </div> <div class="input-session license-input"> <div class="input-title"><h4>자격증</h4></div> <div class="input-box"> <div> <p> <input type="text" name="licenseName" class="boxTF" style="width: 27%;" placeholder="자격증명을 입력하세요"> <input type="date" name="licenseDate" class="boxTF" style="width: 27%;" placeholder="자격증취득날짜를 입력하세요"> <span class="licenseRemoveBtn" style="float: right;"><i class="far fa-minus-square"></i></span> </p> </div> <div style="text-align: center; margin-top: 10px;"> <button type="button" class="btn licenseAddBtn">추가</button> </div> </div> </div> <div class="member-confirm"> <button type="button" class="btn" onclick="sendOk();"> 회원가입 </button> <button type="reset" class="btn"> 다시입력 </button> <button type="button" class="btn"> 가입취소 </button> </div> </div> </form> </div> </div> </body> </html>
member.jsp
회원가입 입력하는 메인 화면 창
입력 양식 검사하는 자바스크립트도 포함되어 있다.
package com.sp.app.member; import java.util.List; public class Member { private String userId; private String userPwd; private String userName; private List<String> schoolName; private List<String> schoolDate1; private List<String> schoolDate2; private List<String> licenseName; private List<String> licenseDate; public List<String> getSchoolName() { return schoolName; } public void setSchoolName(List<String> schoolName) { this.schoolName = schoolName; } public List<String> getSchoolDate1() { return schoolDate1; } public void setSchoolDate1(List<String> schoolDate1) { this.schoolDate1 = schoolDate1; } public List<String> getSchoolDate2() { return schoolDate2; } public void setSchoolDate2(List<String> schoolDate2) { this.schoolDate2 = schoolDate2; } public List<String> getLicenseName() { return licenseName; } public void setLicenseName(List<String> licenseName) { this.licenseName = licenseName; } public List<String> getLicenseDate() { return licenseDate; } public void setLicenseDate(List<String> licenseDate) { this.licenseDate = licenseDate; } public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserPwd() { return userPwd; } public void setUserPwd(String userPwd) { this.userPwd = userPwd; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
입력한 값들을 저장하기 위해서 Member.java를 만든다.
특이점은 추가된 항목들을 저장하기 위해서 list 형태로 만든 것.
package com.sp.app.member; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; @Controller("member.memberController") @RequestMapping("/signup/*") public class MemberController { @GetMapping("member") public String writeForm() throws Exception { return "signup/member"; } @PostMapping("member") public String memberSubmit(Member dto, Model model) throws Exception { model.addAttribute("dto", dto); return "signup/result"; } }
MemberController.java
@Controller의 역할은 Model 객체를 만들어 데이터를 담고 View를 찾는 것
그러니까 @Controller("member.memberController") 를 넣어줘야 데이터가 왔다갔다가 가능하다.
(통상 클래스 이름에서 맨 앞글자만 소문자로하고 나머지는 동일)
@GetMapping("member") public String writeForm() throws Exception { return "signup/member"; }
GET 방식으로 들어왔으면 다시 메인 화면으로 돌아가라 라는 뜻
@PostMapping("member") public String memberSubmit(Member dto, Model model) throws Exception { model.addAttribute("dto", dto); return "signup/result"; }
POST방식으로 들어왔을때의 수행 코드
아까 만든 Member의 객체를 받고, 데이터 전송을 위해서 Model model을 인자로 받음
그리고 dto를 그대로 dto라는 이름으로 어트리뷰트에 저장
<%@ page contentType="text/html; charset=UTF-8"%> <%@ page trimDirectiveWhitespaces="true" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> <link rel="icon" href="data:;base64,iVBORw0KGgo="> </head> <body> <h3>결과</h3> <div> <ul> <li>${dto.userName }</li> <li>${dto.userId }</li> <li>${dto.userPwd }</li> <c:forEach var="item" items="${dto.schoolName }" varStatus="status"> <li>${item } : ${dto.schoolDate1[status.index] } ~ ${dto.schoolDate2[status.index]}</li> </c:forEach> <c:forEach var="item" items="${dto.licenseName }" varStatus="status"> <li>${item } : ${dto.licenseDate }[status.index]</li> </c:forEach> </ul> </div> </body> </html>
result.jsp
결과창에서 출력할때 dto안에 있는 리스트들을 보여줘야 한다.
<li>${dto.userName }</li>
<li>${dto.userId }</li>
<li>${dto.userPwd }</li> 이건 간단하게 이름 아이디 패스워드는 한줄로 끝난다.<c:forEach var="item" items="${dto.schoolName }" varStatus="status"> <li>${item } : ${dto.schoolDate1[status.index] } ~ ${dto.schoolDate2[status.index]}</li> </c:forEach>
여기서 리스트에 있는 내용들을 전부 출력하기 위해서 forEach문을 사용했고
varStatus를 통해서 인덱스 작업을 한다.
dto.schoolName에는 여러 이름들이 저장되어 있을것이고 이걸 var item에 담아서
HTML 코드에서 사용을한다.
status.index를 사용하면 인덱스를 사용할 수 있다.
저 한줄이 하나의 항목이 된다.
반응형