반응형

 

sweetalert

 

 

css와 js 파일 집어 넣기

 

create.jsp
상단에 경로 추가 (css 파일, js 파일이 있는 위치로 변경해야함)

<link rel="stylesheet" href="/resources/css/sweetalert2.min.css">
<script type="text/javascript" src="/resources/js/sweetalert2.min.js"></script>

 

기존 스크립트에 수정

	$("#btnPost").on("click",function(){
		new daum.Postcode({
			//다음 창에서 검색이 완료되면 콜백함수에 의해 결과 데이터가 data 객체로 들어옴
			oncomplete:function(data) {
				$("#postNum").val(data.zonecode);
				$("input[name='empAddress']").val(data.address);
				$("#empAddress2").val(data.buildingName);
				
				//sweetalert 띄우기 (3초간)
				var Toast = Swal.mixin({
					//환경설정
					toast:true,
					position:"top-end",
					showConfirmButton:false, //확인 버튼 -> 확인 받을 필요가 있는지
					timer:3000
				});
				Toast.fire({
					//success, error, warning, info, question 등등
					icon:"success", //녹색
					title:"우편번호가 검색되었습니다.", //내용
				});
			}
		}).open();
	});

 

결과 화면1

 

 

 

모달 이용

 

 

모달 html 파일

 

 

<!-- 모달을 띄우는 방법
1. button으로 띄우기
<button type="button" class="btn btn-default" 
data-toggle="modal" data-target="#modal-default">
Launch Default Modal
</button>

2. a 태그로 띄우기
<a data-toggle="modal" href="#modal-default">Open Modal</a>

3. 기타 요소로 띄우기
<p data-toggle="modal" data-target="#modal-default">Open Modal</p>
 -->
<!-- bookVO -> attachVOList 멤버변수 -> List<AttachVO> 
JSTL누적 : 

c set var="auth" value=""

c set var="auth" value="달러{auth += ' ' += 누적할값}
-->

$('#id').modal('show');
$('#id').modal('hide');

 

 

 

  • 실습

list.jsp
하단에 추가

	<!-- 3. 기타 요소로 띄우기 -->
	<p data-toggle="modal" data-target="#modal-lg">Open Modal</p>
	<!-- ////// 직원 상세 모달 시작 ////// -->
	<div class="modal fade" id="modal-lg">
		<div class="modal-dialog modal-lg">
			<div class="modal-content">
				<div class="modal-header">
					<h4 class="modal-title">Large Modal</h4>
					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
						<span aria-hidden="true">&times;</span>
					</button>
				</div>
				<div class="modal-body">
					<p>One fine body&hellip;</p>
				</div>
				<div class="modal-footer justify-content-between">
					<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
					<button type="button" class="btn btn-primary">Save changes</button>
				</div>
			</div>
		</div>
	</div>
	<!-- ////// 직원 상세 모달 끝 ////// -->

 

테이블 부분 수정

	<table border="1">
		<thead>
			<tr>
				<th>직원 번호</th><th>직원 명</th><th>직원 주소</th>
				<th>직원 연락처</th><th>직원 급여</th><th>파일 이름</th>
			</tr>
		</thead>
		<tbody id="trShow">
			<c:forEach var="employeeVO" items="${articlePage.content}" varStatus="stat">
				<tr>
					<td data-toggle="modal" data-target="#modal-lg">${employeeVO.empNo}</td>
<%-- 					<td><a href="/employee/detail?empNo=${employeeVO.empNo}">${employeeVO.empNo}</a></td> --%>
					<td>${employeeVO.empName}</td>
					<td>${employeeVO.empAddress}</td>
					<td>${employeeVO.empTelno}</td>
					<td>${employeeVO.empSalary}</td>
					<td>${employeeVO.filename}</td>
				</tr>
			</c:forEach>
		</tbody>
	</table>

 

 

현재 list.jsp 파일

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/resources/js/jquery.min.js"></script>
<title>직원 목록</title>
<script type="text/javascript">
$(function(){
	$("#btnSearch").on("click",function(){
		let keyword = $("input[name='keyword']").val();
		
// 		$(this).parent().submit();

		//json 오브젝트
		let data = {
			"keyword":keyword
		};
		
		console.log("data : ", data);
		
		getList(keyword,1);
	});
	
	$("#btnSearchAll").on("click",function(){
		getList("",1);
	});
	
	getList("");
});

function getList(keyword, currentPage) {
	let data = {
		"keyword":keyword,
		"currentPage":currentPage
	};
	
	$.ajax({
		url:"/employee/listAjax",
		contentType:"application/json;charset=utf-8",
		data:JSON.stringify(data),
		type:"post",
		dataType:"json",
		success:function(result){
			console.log("result.content : ", result.content);
			
			let str = "";
			
			$.each(result.content, function(idx, employeeVO){
				str += "<tr>";
				str +="<td><a href='/employee/detail?empNo=" + employeeVO.empNo + "'>" + employeeVO.empNo + "</a></td>";
				str +="<td>" + employeeVO.empName + "</td>";
				str +="<td>" + employeeVO.empAddress + "</td>";
				str +="<td>" + employeeVO.empTelno + "</td>";
				str +="<td>" + employeeVO.empSalary + "</td>";
				str +="<td>" + employeeVO.filename + "</td>";
				str += "</tr>";
			});
			$(".clsPagingArea").html(result.pagingArea);
			
			$("#trShow").html(str);
		}
	});
}
</script>
</head>
<body>
	<h3>직원 목록</h3>
	
	<p>
	<form>
		<input type="text" name="keyword" value="" placeholder="검색어를 입력하세요"/>
		<!-- submit / button / reset -->
			<button type="button" id="btnSearch">검색</button>
			<button type="button" id="btnSearchAll">전체보기</button>
		</form>
		<a href="/create">도서 등록</a>
	</p>
	
	<table border="1">
		<thead>
			<tr>
				<th>직원 번호</th><th>직원 명</th><th>직원 주소</th>
				<th>직원 연락처</th><th>직원 급여</th><th>파일 이름</th>
			</tr>
		</thead>
		<tbody id="trShow">
			<c:forEach var="employeeVO" items="${articlePage.content}" varStatus="stat">
				<tr>
					<td data-toggle="modal" data-target="#modal-lg">${employeeVO.empNo}</td>
<%-- 					<td><a href="/employee/detail?empNo=${employeeVO.empNo}">${employeeVO.empNo}</a></td> --%>
					<td>${employeeVO.empName}</td>
					<td>${employeeVO.empAddress}</td>
					<td>${employeeVO.empTelno}</td>
					<td>${employeeVO.empSalary}</td>
					<td>${employeeVO.filename}</td>
				</tr>
			</c:forEach>
		</tbody>
	</table>

	<!-- 3. 기타 요소로 띄우기 -->
	<p data-toggle="modal" data-target="#modal-lg">Open Modal</p>
	<!-- ////// 직원 상세 모달 시작 ////// -->
	<div class="modal fade" id="modal-lg">
		<div class="modal-dialog modal-lg">
			<div class="modal-content">
				<div class="modal-header">
					<h4 class="modal-title">Large Modal</h4>
					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
						<span aria-hidden="true">&times;</span>
					</button>
				</div>
				<div class="modal-body">
					<p>One fine body&hellip;</p>
				</div>
				<div class="modal-footer justify-content-between">
					<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
					<button type="button" class="btn btn-primary">Save changes</button>
				</div>
			</div>
		</div>
	</div>
	<!-- ////// 직원 상세 모달 끝 ////// -->


	<hr />
	<div class="row clsPagingArea">
		${articlePage.pagingArea}
	</div>
</body>
</html>

결과 화면2 : 직원 번호 클릭 시 모달 작동

 

 

 

  • 직원 상세 보기 기능 넣기

list.jsp

class 추가 및 변경

<td class="clsEmpNo" data-toggle="modal" data-target="#modal-lg"
    data-emp-no="${employeeVO.empNo}">${employeeVO.empNo}</td>

 

자바 스크립트에 추가

$(function(){
	//모달로 직원 상세 보기
	$(".clsEmpNo").on("click",function(){
		console.log("clsEmpNo에 왔다");
		
		//data-emp-no="A014"
		//this : 동일 클래스 속성의 오브젝트 배열 중에서 클릭한 바로 그 오브젝트 
		//<td class="clsEmpNo" data-toggle="modal" data-target="#modal-lg" data-emp-no="A511">A511</td>
		let empNo = $(this).data("empNo");
		console.log("empNo : ", empNo);
	});
});

 

결과 화면3 : 클릭 시 empNo 값 출력

 

 

 

  • 비동기 통신

EmployeeController.java

새로 추가

/*
요청 URI : /employee/detailAjax
요청 파라미터(JSON.stringify) : {"empNo" : "A013"}
요청 방식 : post
 */

//비동기(Asynchronous) : 1) RequestBody(JSON.stringify받음) / ResponseBody(JSON보냄)
@ResponseBody
@PostMapping(value="/detailAjax")
public EmployeeVO detailAjax(@RequestBody EmployeeVO employeeVO) {
    log.info("detailAjax->employeeVO : " + employeeVO);

    employeeVO = this.employeeService.detail(employeeVO);
    log.info("detailAjax->employeeVO : " + employeeVO);

    //2) return 데이터
    return employeeVO;
}

 

list.jsp

ajax 추가

$(function(){
	//모달로 직원 상세 보기
	$(".clsEmpNo").on("click",function(){
		console.log("clsEmpNo에 왔다");
		
		//data-emp-no="A014"
		//this : 동일 클래스 속성의 오브젝트 배열 중에서 클릭한 바로 그 오브젝트 
		//<td class="clsEmpNo" data-toggle="modal" data-target="#modal-lg" data-emp-no="A511">A511</td>
		let empNo = $(this).data("empNo");
		console.log("empNo : ", empNo);
		
		//JSON 오브젝트
		let data = {
			"empNo":empNo
		};
		
		console.log("data : ", data);
		
		/*
		요청 URI : /employee/detailAjax
		요청 파라미터(JSON.stringify) : {"empNo" : "A013"}
		요청 방식 : post
		 */
		 //아작나써유..(피)씨다타써.
		 $.ajax({
			url:"/employee/detailAjax",
			contentType:"application/json;charset=utf-8",
			data:JSON.stringify(data),
			type:"post",
			beforeSend:function(xhr){
				xhr.setRequestHeader("${_csrf.headerName}","${_csrf.token}");
			},
			success:function(result){
				console.log("result : ", result);
			}
		 });
	});
});

 

결과 화면4

 

결과 화면5

 

 

 

  • 모달 창 안에 값 출력

list.jsp

모달 부분 수정

	<!-- 3. 기타 요소로 띄우기 -->
	<p data-toggle="modal" data-target="#modal-lg">Open Modal</p>
	<!-- ////// 직원 상세 모달 시작 ////// -->
	<div class="modal fade" id="modal-lg">
		<div class="modal-dialog modal-lg">
			<div class="modal-content">
				<div class="modal-header">
					<h4 class="modal-title">Large Modal</h4>
					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
						<span aria-hidden="true">&times;</span>
					</button>
				</div>
				<div class="modal-body">
					<p><input type="text" name="empNo" placeholder="직원 번호" /></p>
					<p><input type="text" name="empName" class="formdata" placeholder="직원 명" /></p>
					<p><input type="text" name="empAddress" class="formdata" placeholder="직원 주소" /></p>
					<p><input type="text" name="empTelno" class="formdata" placeholder="직원 연락처" /></p>
					<p><input type="number" name="empSalary" class="formdata" placeholder="직원 급여" /></p>
					<p>
						<img src="" name="filename" class="formdata" />
					</p>
				</div>
				<div class="modal-footer justify-content-between">
					<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
				</div>
			</div>
		</div>
	</div>
	<!-- ////// 직원 상세 모달 끝 ////// -->

 

스크립트 부분(ajax) 수정

 //아작나써유..(피)씨다타써.
 $.ajax({
    url:"/employee/detailAjax",
    contentType:"application/json;charset=utf-8",
    data:JSON.stringify(data),
    type:"post",
    beforeSend:function(xhr){
        xhr.setRequestHeader("${_csrf.headerName}","${_csrf.token}");
    },
    success:function(result){
        console.log("result : ", result);

        $("input[name='empNo']").val(result.empNo);
        $("input[name='empName']").val(result.empName);
        $("input[name='empAddress']").val(result.empAddress);
        $("input[name='empTelno']").val(result.empTelno);
        $("input[name='empSalary']").val(result.empSalary);
// 		$("img[name='filename']").attr("src","/resources/upload"+result.filename);
        // 위의 것과 같이 쓸 수 있음
        document.getElementsByName("filename")[0].src = "/resources/upload" + result.filename;
    }
 });

 

결과 화면6

 

 

+다른 예시

더보기

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/resources/js/jquery.min.js"></script>
<title>도서 목록</title>
<script type="text/javascript">
$(function(){
	//도서 상세 모달
	$(".clsBookId").on("click",function(){
		let bookId = $(this).data("bookId"); //135
		console.log("bookId : ", bookId);
		
		let data = {
			"bookId":bookId
		};
		
		//아작나써유..(피)씨다타써
		//contentType : 보내는 타입
		$.ajax({
			url:"/detailAjax",
			contentType:"application/json;charset=utf-8",
			data: JSON.stringify(data),
			type:"post",
			dataType:"json",
			beforeSend:function(xhr){
				xhr.setRequestHeader("${_csrf.headerName}","${_csrf.token}");
			},
			success:function(result) {
				console.log("result : ", result);
				
				$("#modalBookTitle").html(result.title);
				$("#modalCategory").val(result.category);
				$("#modalPrice").val(result.price);
				$("#modalInsertDate").val(result.insertDatestr);
				
			}
		});
	});
	
	
	$("#btnSearch").on("click",function(){
		let keyword = $("input[name='keyword']").val();
		
		//json오브젝트
		let data = {
			"keyword":keyword
		};
		
		console.log("data : ", data);
		
 		//$(this).parent().submit();
 		//새롭게 검색 : 1페이지로 초기화
		getList(keyword,1);
	});
	
	// 전체 보기
	$("#btnSearchAll").on("click",function(){
		getList("",1);
	});
	
	
	// 목록 함수 호출
// 	getList("");
});

// 목록
function getList(keyword, currentPage) {
	
	// JSON 오브젝트
	let data = {
		"keyword":keyword,
		"currentPage":currentPage
	};
	// data : {"keyword":"알탄","currentPage":"1"}
	console.log("data : ", data);
	
	//아작나써유..(피)씨다타써...
	$.ajax({
		url: "/listAjax",
		contentType:"application/json;charset=utf-8",
		data:JSON.stringify(data),
		type:"post",
		dataType:"json",
		success:function(result){
			// result : articlePage
			// result.content : List<BookVO>
			console.log("result.content : ", result.content);
			
			let str = "";
			
			$.each(result.content, function(idx, bookVO){
				str += "<tr>";
				str += "<td>" + (idx+1) + "</td>";
				str += "<td><a href='/detail?bookId=" + bookVO.bookId + "'>" + bookVO.title + "</a></td>";
				str += "<td>" + bookVO.category + "</td>";
				str += "<td>" + bookVO.price + "원</td>";
				str += "</tr>";
			});
			
			$(".clsPagingArea").html(result.pagingArea);
			
			$("#trShow").html(str);
		}
	});
}

</script>
</head>
<body>
<h3>도서 목록</h3>
<p>
	<!-- action속성 및 값이 생략 시, 현재 URI(/list)를 재요청. 
		method는 GET(form 태그의 기본 HTTP 메소드는 GET임) 
	param : keyword=알탄
	요청URI : /list?keyword=알탄 or /list or /list?keyword=
	요청파라미터 : keyword=알탄
	요청방식 : get
	-->
	<form>
		<input type="text" name="keyword" value="" placeholder="검색어를 입력하세요"/>
		<!-- submit / button / reset -->
		<button type="button" id="btnSearch">검색</button>
		<button type="button" id="btnSearchAll">전체보기</button>
	</form>
	<a href="/create">도서 등록</a>
</p>
<!-- mav.addObject("bookVOList", bookVOList) -->
<%-- <p>${bookVOList}</p> --%>
<table border="1">
	<thead>
		<tr>
			<th>번호</th><th>제목</th><th>카테고리</th><th>가격</th>
		</tr>
	</thead>
	<tbody id="trShow">
		<!-- 
		forEach 태그? 배열(String[], int[][]), Collection(List, Set) 또는 
		Map(HashTable, HashMap, SortedMap)에 저장되어 있는 값들을 
		순차적으로 처리할 때 사용함. 자바의 for, do~while을 대신해서 사용함
		var : 변수
		items : 아이템(배열, Collection, Map)
		varStatus : 루프 정보를 담은 객체 활용
		   - index : 루프 실행 시 현재 인덱스(0부터 시작)
		   - count : 실행 회수(1부터 시작. 보통 행번호 출력)
		 -->
		<!-- data : mav.addObject("articlePage", 페이지네이션객체); -->
		<!-- articlePage.content => List<BookVO> -->
		<!-- row : bookVO 1행 -->
		<c:forEach var="bookVO" items="${articlePage.content}" varStatus="stat">
			<tr>
				<td class="clsBookId" data-toggle="modal" data-target="#modalBook"
					data-book-id="${bookVO.bookId}">${bookVO.rnum}</td>
				<td><a href="/detail?bookId=${bookVO.bookId}">${bookVO.title}</a></td>
				<td>${bookVO.category}</td>
				<td><fmt:formatNumber value="${bookVO.price}" pattern="#,###" />원</td>
			</tr>
		</c:forEach>
	</tbody>
</table>
<hr />
<div class="row clsPagingArea">
	${articlePage.pagingArea}
</div>

	<!-- ////// 상세 모달 시작 ////// -->
	<div class="modal fade" id="modalBook">
		<div class="modal-dialog modal-lg">
			<div class="modal-content">
				<div class="modal-header">
					<h4 class="modal-title" id="modalBookTitle"></h4>
					<button type="button" class="close" data-dismiss="modal" aria-label="Close">
						<span aria-hidden="true">&times;</span>
					</button>
				</div>
				<div class="modal-body" id="modalBookBody">
					<p>카테고리 : <input type="text" id="modalCategory" readonly /></p>
					<p>가&nbsp;&nbsp;&nbsp;격 : <input type="text" id="modalPrice" readonly /></p>
					<p>등&nbsp;록&nbsp;일 : <input type="text" id="modalInsertDate" readonly /></p>
				</div>
				<div class="modal-footer justify-content-between">
					<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
					<button type="button" class="btn btn-primary">Save changes</button>
				</div>
			</div>
		</div>
	</div>
	<!-- ////// 상세 모달 끝 ////// -->

</body>
</html>

 

 

BookController.java

package kr.or.ddit.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;


import kr.or.ddit.service.BookService;
import kr.or.ddit.utils.ArticlePage;
import kr.or.ddit.vo.BookVO;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
public class BookController {
	
	@Autowired
	BookService bookService;
	
	/*
	요청URI : /list?keyword=알탄 or /list or /list?keyword=
	요청파라미터 : keyword=알탄 or 없음
	요청방식 : get
	
	required=false : 선택사항. 파라미터가 없어도 무관
	*/
	@RequestMapping(value="/list", method=RequestMethod.GET)
	public ModelAndView list(ModelAndView mav, 
			@RequestParam(value="currentPage",required=false,defaultValue="1") int currentPage,
			@RequestParam(value="keyword",required=false,defaultValue="") String keyword) {
		log.info("list에 왔다");
		log.info("list->keyword : " + keyword);
		
		//map{"keyword":"알탄"}
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("keyword", keyword);
		map.put("currentPage", currentPage);
		
		
		//도서 전체 행수
		int total = this.bookService.getTotal(map);
		log.info("list->total : " + total);
		
		
		//도서 목록 map{"keyword":"알탄"}
		List<BookVO> bookVOList = this.bookService.list(map);
		log.info("list->bookVOList : " + bookVOList);
		
		//Model : 데이터
		mav.addObject("articlePage", new ArticlePage<BookVO>(total, currentPage, 10, bookVOList, keyword));
		
		//View : jsp
		//forwarding : 데이터가 넘어감
		mav.setViewName("book/list");
		
		return mav;
	}
    
	//비동기 :	1) RequestBody로 JSON 받기
	//			2) ResponseBody로 JSON 보내기
	@ResponseBody
	@PostMapping(value="/detailAjax")
	public BookVO detailAjax(@RequestBody BookVO bookVO) {
		log.info("detailAjax->bookVO : " + bookVO);
		
		//호출 전 : {"bookId":"3","title":null,"category":null,"price":0,"insertDate":null}
		//도서 상세
		bookVO = this.bookService.detail(bookVO);
		
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		bookVO.setInsertDatestr(formatter.format(bookVO.getInsertDate()));
		
		return bookVO;
	}
}

 

 

BookVO.java

package kr.or.ddit.vo;

import java.util.Date;

import org.springframework.web.multipart.MultipartFile;

import lombok.Data;

@Data
public class BookVO {
	private int rnum;
	private int bookId;
	private String title;
	private String category;
	private int price;
	private Date insertDate;
	private String insertDatestr;
	
	//BOOK : ATTACH = 1 : N
	private MultipartFile[] pictures;
}

 

결과 화면7

 

 

 

  • 수정 기능 추가

list.jsp
모달 부분 추가

<!-- ////// 상세 모달 시작 ////// -->
<div class="modal fade" id="modalBook">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h4 class="modal-title" id="modalBookTitle"></h4>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body" id="modalBookBody">
                <p>카테고리 : <input type="text" class="form-control clsInput" id="modalCategory" readonly /></p>
                <p>가&nbsp;&nbsp;&nbsp;격 : <input type="text" class="form-control clsInput" id="modalPrice" readonly /></p>
                <p>등&nbsp;록&nbsp;일 : <input type="text" class="form-control clsInput" id="modalInsertDate" readonly /></p>
            </div>
            <div class="modal-footer justify-content-between">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary btnEdit" id="btnModify">수정</button>
                <button type="button" class="btn btn-success btnConfirm" style="display:none;" id="btnOk">확인</button>
                <button type="button" class="btn btn-warning btnConfirm" style="display:none;" id="btnCancel">취소</button>
            </div>
        </div>
    </div>
</div>
<!-- ////// 상세 모달 끝 ////// -->

 

테이블 부분의 data-book-id 추가 및 수정

<table border="1">
	<thead>
		<tr>
			<th>번호</th><th>제목</th><th>카테고리</th><th>가격</th>
		</tr>
	</thead>
	<tbody id="trShow">
		<!-- 
		forEach 태그? 배열(String[], int[][]), Collection(List, Set) 또는 
		Map(HashTable, HashMap, SortedMap)에 저장되어 있는 값들을 
		순차적으로 처리할 때 사용함. 자바의 for, do~while을 대신해서 사용함
		var : 변수
		items : 아이템(배열, Collection, Map)
		varStatus : 루프 정보를 담은 객체 활용
		   - index : 루프 실행 시 현재 인덱스(0부터 시작)
		   - count : 실행 회수(1부터 시작. 보통 행번호 출력)
		 -->
		<!-- data : mav.addObject("articlePage", 페이지네이션객체); -->
		<!-- articlePage.content => List<BookVO> -->
		<!-- row : bookVO 1행 -->
		<c:forEach var="bookVO" items="${articlePage.content}" varStatus="stat">
			<tr>
				<td class="clsBookId" data-toggle="modal" data-target="#modalBook"
					data-book-id="${bookVO.bookId}">${bookVO.rnum}</td>
				<td><a href="/detail?bookId=${bookVO.bookId}">${bookVO.title}</a></td>
				<td>${bookVO.category}</td>
				<td><fmt:formatNumber value="${bookVO.price}" pattern="#,###" />원</td>
			</tr>
		</c:forEach>
	</tbody>
</table>


스크립트 부분 추가 

$(function(){
	//수정 버튼 클릭
	$("#btnModify").on("click", function(){
		$(".btnEdit").css("display", "none");
		$(".btnConfirm").css("display", "block");
		
		$(".clsInput").removeAttr("readonly");
		
		//sessionStorage(자바스크립트의 세션)에 변경 전 데이터를 저장함
		sessionStorage.setItem("category",$("#modalCategory").val());
		sessionStorage.setItem("price",$("#modalPrice").val());
		sessionStorage.setItem("insertDate",$("#modalInsertDate").val());
	});
	
	$("#btnCancel").on("click", function(){
		$(".btnEdit").css("display", "block");
		$(".btnConfirm").css("display", "none");
		
		$(".clsInput").attr("readonly",true);
		
		//변경 전 저장된 sessionStorage(자바스크립트의 세션) 데이터를 블러옴
		$("#modalCategory").val(sessionStorage.getItem("category"));
		$("#modalPrice").val(sessionStorage.getItem("price"));
		$("#modalInsertDate").val(sessionStorage.getItem("insertDate"));
	});
	
	$("#btnOk").on("click",function(){
		let category = $("#modalCategory").val();
		let price = $("#modalPrice").val();
		let insertDate = $("#modalInsertDate").val();
		
		let data = {
			"bookId":sessionStorage.getItem("bookId"),
			"category":category,
			"price":price,
			"insertDate":insertDate
		};
		console.log("data : ", data);
		
		
		//아작나써유..(피)씨다타써
		//contentType : 보내는 타입
		$.ajax({
			url:"/updataAjax",
			contentType:"application/json;charset=utf-8",
			data: JSON.stringify(data),
			type:"post",
			dataType:"json",
			beforeSend:function(xhr){
				xhr.setRequestHeader("${_csrf.headerName}","${_csrf.token}");
			},
			success:function(result) {
				console.log("result : ", result);
				
				$(".btnEdit").css("display","none");
				$(".btnConfirm").css("display","block");
				$(".clsInput").removeAttr("readonly");
   
				var Toast = Swal.mixin({
					toast: true,
					position: 'top-end',
					showConfirmButton: false,
					timer: 3000
				});

				Toast.fire({
					icon : 'success',
					title: '변경되었습니다.'
				});
   
				//목록 불러오기
				getList("",1);
				
				//모달닫기
				$ ("#modalBook").modal("hide");
			}
		});
	});
	
	
	//도서 상세 모달
	$(".clsBookId").on("click",function(){
		let bookId = $(this).data("bookId"); //135
		console.log("bookId : ", bookId);
		
		sessionStorage.setItem("bookId",bookId);
		
		let data = {
			"bookId":bookId
		};
		
		//아작나써유..(피)씨다타써
		//contentType : 보내는 타입
		$.ajax({
			url:"/detailAjax",
			contentType:"application/json;charset=utf-8",
			data: JSON.stringify(data),
			type:"post",
			dataType:"json",
			beforeSend:function(xhr){
				xhr.setRequestHeader("${_csrf.headerName}","${_csrf.token}");
			},
			success:function(result) {
				console.log("result : ", result);
				
				$("#modalBookTitle").html(result.title);
				$("#modalCategory").val(result.category);
				$("#modalPrice").val(result.price);
				$("#modalInsertDate").val(result.insertDatestr);
			}
		});
	});
});

 

상단에 스크립트와 link 추가

<link rel="stylesheet" src="/resources/css/sweetalert2.min.css"></script>
<script type="text/javascript" src="/resources/js/sweetalert2.min.js"></script>

 

결과 화면8-1 : 리스트에서 모달 화면

 

결과 화면8-2 : 수정 버튼 클릭 화면

 

결과 화면8-3 : 수정 후 화면

 

 

 

사진 파일 D드라이브에 저장

 

 

업로드 되는 폴더 위치 / 폴더 미리 생성해야함

 

 

servlet-context.xml

</beans:beans> 안에 추가

<!-- 첨부파일 전용 폴더 매핑 -->
<resources mapping="/upload/**" location="file:///D:/upload" />

 

 

 

  • 스프링 시큐리티에서 submit할 때 파일 업로드 시 
?${_csrf.parameterName}=${_csrf.token}

 

를 뒤에 추가하지 않으면 파일이 올라가지 않음

 


create.jsp

ClassicEditor 부분에 추가

ClassicEditor.create(document.querySelector('#ckMessage'),{ckfinder:{uploadUrl:'/image/upload?${_csrf.parameterName}=${_csrf.token}'}})
   .then(editor=>{window.editor=editor;})
   .catch(err=>{console.error(err.stack);});

 

결과 화면9

 

 

 

  • 파일 업로드 기능

create.jsp

상단에 추가

<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>

 

</form> 안에 추가

<sec:csrfInput/>

 

form 태그 변경

action의 뒤에 ?${_csrf.parameterName}=${_csrf.token} 가 추가되어야 함

<form id="frm" name="frm" action="/contUs/createPost?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form-data">

 

결과 화면10-1

 

결과 화면10-2 : 데이터 들어가는 테이블

 

결과 화면10-3 : 추가된 것 확인

 

 

 

TIP

 

 

[스프링시큐리티 및 csrf토큰 비활성화 방법]

 

1. web.xml의 filter, contextConfigLocation
2. security-context.xml에서 <security:csrf disabled="true" />

 

 

반응형