Eggs Sunny Side Up
본문 바로가기
프레임워크(Framework)/Spring

[Spring] fullcalendar DB연동 및 일자별 클릭 후 리스트 출력

by guswn100059 2023. 8. 3.

jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<!-- fullcalendar CDN -->
<link href='https://cdn.jsdelivr.net/npm/fullcalendar@5.8.0/main.min.css' rel='stylesheet' />
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.8.0/main.min.js'></script>
<!-- fullcalendar 언어 CDN -->
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.8.0/locales-all.min.js'></script>
</head>
<body class="sb-nav-fixed">

	<div class="calendar_page" id="page2-content" style="display: none;" value="데이터조회">

		<div id="calendar" class="calendar_size"></div>
		<p class="date" id="nows"></p>

	</div>

</body>
</html>

fullcalendar 불러오는 방법

1. CDN 주소 가져오기

https://www.jsdelivr.com/package/npm/fullcalendar

2. 파일 다운받은 후 코드 작성

https://fullcalendar.io/docs/initialize-globals

 


DB연동

Controller

package kr.mds.controller;

@RestController
public class mainRestController {
	
	@Autowired
	private UserMapper mapper;
	
	@Autowired
	private Security_alarm_carMapper sacmapper;
	
	@Autowired
	private Security_alarm_humanMapper sahmapper;
	
	
	// 캘린더 DB연동
	@GetMapping("/calendarDB.com")
	public String calendarDB(@RequestParam("u_id") String u_id) {
		Map<String, List<?>> result = new HashMap<>();
		System.out.println(u_id);
		List<tb_Security_alarm_human> sah = sahmapper.calendarSah(u_id);
		result.put("sah", sah);
		List<tb_Security_alarm_car> sac = sacmapper.calendarSac(u_id);
		result.put("sac", sac);
		System.out.println(result);
		
		// List 배열을 json으로 데이터변환
		String json = new Gson().toJson(result);
		System.out.println(json);
		
		return json;
	}	
}

https://deersoul6662.tistory.com/214

=> List 배열 형태는 json으로 넘어가지 않기 때문에 무조건 넘어가는 데이터를 변환시켜줘야 함!!!

 

JS

events: function(info, successCallback, failureCallback){
			
	        $.ajax({
	        	url:'calendarDB.com',
	        	type: 'get',
	        	dataType: 'json',
	        	data: {'u_id':data},
	        	success: function(res){
	        		/*console.log(res);
	        		console.log((res.sac[0].car_num));
	        		console.log(res.sac[0].sac_in_at);
	        		console.log(typeof(res.sac[0].sac_in_at));
	        		console.log((res.sac[0].sac_in_at).substring(0,10));*/
	    			
	        		var events = [];
	        		for(var i = 0; i < (res.sac).length; i++){
		        		res.sac[i].sac_in_at = (res.sac[i].sac_in_at).substring(0,10);
		        		
		        		events.push({
		        			title : '차량 '+res.sac[i].sac_in_count+'대 침입',
		        			start : res.sac[i].sac_in_at,
		        			end : res.sac[i].sac_in_at,
		        			color : "#FF0000"
		        		})
	        		}
	        		
	        		for(var i = 0; i < (res.sah).length; i++) {
	        			res.sah[i].sah_in_at = (res.sah[i].sah_in_at).substring(0,10);
	        			
	        			events.push({
	        				title : '사람 '+res.sah[i].sah_in_count+'명 침입',
		        			start : res.sah[i].sah_in_at,
		        			end : res.sah[i].sah_in_at,
		        			color : "#FFFF00",
		        			textColor : 'black'
	        			})
	        		}
	        		console.log(events)
	        		successCallback(events);
	        		
	        	},
	        	error: function(e){
	        		alert("요청 실패");
	        	}
	        })
	     }

ajax를 이용하여 DB에서 받아온 데이터를 일자별로 출력해주는 방식

https://stackoverflow.com/questions/67134386/events-not-displaying-after-fetching-from-database-using-ajax-on-fullcalendar-v5

 

결과화면

 


일자별 클릭

https://fullcalendar.io/docs/dateClick

https://fullcalendar.io/docs/v3/dayClick

=> fullcalendar 문서를 기반으로 코드 작성하는게 구글링보다 편함!

 

JS

// 날짜 클릭 시 리스트 출력
        eventClick: function(date, calEvent, jsEvent, view){
           /*console.log(date);*/
           /*console.log(date.event._instance.range.start);*/
           /*const today = date.event._instance.range.start;*/
           /*console.log(today.toISOString().slice(0, 10));*/
           
           $.ajax({
              url:'calendarDB.com',
                 type: 'get',
                 dataType: 'json',
                 contentType: "application/json; charset=UTF-8",
                 data: {'u_id':data},
                 success: function(res){
                    /*console.log(res);
                    console.log(res.sac[0].sac_img_link);*/
                    const today = date.event._instance.range.start.toISOString().slice(0, 10);
                    /*console.log(today);
                    console.log(res.sac[0].sac_in_at.substring(0,10));*/
                    
                    for(var i = 0; i < res.sac.length; i++){
                       if(res.sac[i].sac_in_at.substring(0,10) == today){
                          $('#nows').append(`
                                <div class="epqlf">
                                <div><img src="showImage.com?fileName=\${res.sac[i].sac_img_link}" width="230px" height="150px"></div>
                                <div class="tkdcn">
                                <div>차량침입</div>
                                <div>차량번호 : \${res.sac[i].car_num}</div>
                                <div>침입시간 : \${res.sac[i].sac_in_at}</div>
                                </div>
                                </div>
                                `);
                       }
                    }
                    
                    for(var i = 0; i< res.sah.length; i++){
                       if(res.sah[i].sah_in_at.substring(0,10) == today){
                          $('#nows').append(`
                                <div class="epqlf">
                                <div><img src="showImage.com?fileName=\${res.sah[i].sah_img_link}" width="230px" height="150px"></div>
                                <div class="tkdcn">
                                <div>사람침입</div>
                                <div>\${res.sah[i].sah_in_count}명 침입</div>
                                <div>침입시간 : \${res.sah[i].sah_in_at}</div>
                                </div>
                                </div>
                                `);
                       }
                    }
                    
                    $('#nows').append(`
                          <button id="epqlfBtn" onclick="$('.epqlf').hide();">
                          `);
                    $('#epqlfBtn').click(function(){
                       $('#epqlfBtn').remove();
                    })
                 }
           })
        }

=> DB 데이터가 연동된 날짜를 클릭하면 상세 리스트가 출력된다.

 

버튼 클릭하면 div 태그 hide

http://www.java2s.com/example/javascript/jquery-method-and-property/jquery-to-hide-appended-div.html

 

실행화면


+) 오류 해결 방법

오류 : DB 데이터가 Controller에서는 잘 수집되었지만 ajax로 데이터가 넘어갈 때는 한글이 깨지는 현상

eclipse console창

console창 

view 화면

=> ajax로 넘겨받은 결과가 잘못된 형태로 넘어왔다는 것을 확인

=> 'gson 한글 깨짐'이라는 구글링을 통해 contentType과 url에 produces를 입력해주었지만 오히려 잘만 되던 코드가 오류가 뜸

=> 디버깅을 하기 위해서 클라이언트쪽이 문제인지, 서버쪽이 문제인지 판단해야 하는 상황

=> F12를 누르고 Network를 클릭하여 확인

Response

Headers

=> 이를 보면 ajax에 입력한 contentType:"application/json;charset=UTF-8"과 다른 것을 볼 수 있다.

=> Controller에서 한글이 인식되게끔 데이터를 보내는 방식을 변경

Controller

// 캘린더 DB연동
	@GetMapping("/calendarDB.com")
	public ResponseEntity<String> calendarDB(@RequestParam("u_id") String u_id, HttpServletResponse response) {
		response.setCharacterEncoding("UTF-8");
		
		Map<String, List<?>> result = new HashMap<>();
		
//		System.out.println(u_id);
		List<tb_Security_alarm_human> sah = sahmapper.calendarSah(u_id);
		result.put("sah", sah);
		List<tb_Security_alarm_car> sac = sacmapper.calendarSac(u_id);
		result.put("sac", sac);
//		System.out.println(result);
		
		// List 배열을 json으로 데이터변환
		String json = new Gson().toJson(result);
		System.out.println(json);
		
		HttpHeaders headers = new HttpHeaders();
	    headers.setContentType(MediaType.APPLICATION_JSON_UTF8);

	    return new ResponseEntity<>(json, headers, HttpStatus.OK);

	}

=> 대체적으로 ajax 406 오류가 뜰 때는 객체 형태가 json으로 넘어가지 못할 때 발생하는 것 같았다.

=> 이럴 때는 데이터를 json으로 변환해주는 json-simple이나 gson을 이용하여 올바르게 ajax로 결과값 넘겨주기!

 

fullcalendar JS 총 정리

$(document).on('click', function() {
   var calendarEl = $('#calendar')[0];
    var calendar = new FullCalendar.Calendar(calendarEl, {
       // contentHeight: 600,
        height: '500px', // calendar 높이 설정
       // 너비가 높이의 두 배
        expandRows: true, // 화면에 맞게 높이 재설정
        slotMinTime: '08:00', // Day 캘린더에서 시작 시간
        slotMaxTime: '20:00', // Day 캘린더에서 종료 시간
        // 해더에 표시할 툴바
        headerToolbar: {
            //left: 'prev,next today',
            left: '',
            center: 'title',
            right:'prev,next today'
            //right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
        },
        initialView: 'dayGridMonth', // 초기 로드 될때 보이는 캘린더 화면(기본 설정: 달)
 //       initialDate: '2023-05-11', // 초기 날짜 설정 (설정하지 않으면 오늘 날짜가 보인다.)
        navLinks: false, // 날짜를 선택하면 Day 캘린더나 Week 캘린더로 링크
        editable: true, // 수정 가능?
        selectable: true, // 달력 일자 드래그 설정가능
        nowIndicator: true, // 현재 시간 마크
        dayMaxEvents: true, // 이벤트가 오버되면 높이 제한 (+ 몇 개식으로 표현)
        locale: 'ko', // 한국어 설정
        eventAdd: function(obj) { // 이벤트가 추가되면 발생하는 이벤트
            console.log(obj);
        },
        
        // 달력에 DB 데이터 연동
       events: function(info, successCallback, failureCallback){
         
           $.ajax({
              url:'calendarDB.com',
              type: 'get',
              dataType: 'json',
              contentType: "application/json;charset=UTF-8",
              data: {'u_id':data},
              success: function(res){
                 /*console.log(res);
                 console.log((res.sac[0].car_num));*/
                 /*console.log(res.sac[0].sac_in_at);
                 console.log(typeof(res.sac[0].sac_in_at));
                 console.log((res.sac[0].sac_in_at).substring(0,10));*/
                
                 var events = [];
                 for(var i = 0; i < (res.sac).length; i++){
                    /*res.sac[i].sac_in_at = (res.sac[i].sac_in_at).substring(0,10);*/
                    
                    events.push({
                       title : '차량출입 '+(res.sac[i].sac_in_at).substring(11,),
                       start : (res.sac[i].sac_in_at).substring(0,10),
                       end : (res.sac[i].sac_in_at).substring(0,10),
                       color : "rgb(60,179,113)",
                       textColor : 'white'
                    })
                 }
                 
                 for(var i = 0; i < (res.sah).length; i++) {
                    /*res.sah[i].sah_in_at = (res.sah[i].sah_in_at).substring(0,10);*/
                    
                    events.push({
                       title : '사람출입 '+(res.sah[i].sah_out_at).substring(11, ),
                       start : (res.sah[i].sah_out_at).substring(0,10),
                       end : (res.sah[i].sah_out_at).substring(0,10),
                       color : "rgb(32,178,170)",
                       textColor : 'white'
                    })
                 }
                 
                 for(var i = 0; i < (res.sah).length; i++) {
                    /*res.sah[i].sah_in_at = (res.sah[i].sah_in_at).substring(0,10);*/
                    
                    events.push({
                       title : '사람침입 '+(res.sah[i].sah_in_at).substring(11, ),
                       start : (res.sah[i].sah_in_at).substring(0,10),
                       end : (res.sah[i].sah_in_at).substring(0,10),
                       color : "#FF0000"
                    })
                 }
                 /*console.log(events);*/
                 successCallback(events);
                 
              },
              error: function(e){
                 alert("요청 실패");
              }
           })
        },
        
        // 날짜 클릭 시 리스트 출력
        eventClick: function(date, calEvent, jsEvent, view){
           /*console.log(date);*/
           /*console.log(date.event._instance.range.start);*/
           /*const today = date.event._instance.range.start;*/
           /*console.log(today.toISOString().slice(0, 10));*/
           
           $.ajax({
              url:'calendarDB.com',
                 type: 'get',
                 dataType: 'json',
                 contentType: "application/json; charset=UTF-8",
                 data: {'u_id':data},
                 success: function(res){
                    /*console.log(res);
                    console.log(res.sac[0].sac_img_link);*/
                    const today = date.event._instance.range.start.toISOString().slice(0, 10);
                    /*console.log(today);
                    console.log(res.sac[0].sac_in_at.substring(0,10));*/
                    
                    for(var i = 0; i < res.sac.length; i++){
                       if(res.sac[i].sac_in_at.substring(0,10) == today && res.sac[i].sac_in_count != 0 && res.sac[i].sac_out_count != 0){
                    	   $('#epqlftkdcn').append(`
                            		<div class="epqlf">
                                  <div><img src="showImage.com?fileName=\${res.sac[i].sac_img_link}" width="230px" height="150px"></div>
                                  <div class="tkdcn">
                                  <div>차량침입</div>
                                  <div>차량번호 : \${res.sac[i].car_num}</div>
                                  <div>침입시간 : \${res.sac[i].sac_in_at}</div>
                                  </div>
                                 </div>
                                 
                                 <div class="epqlf">
                                 <div><img src="showImage.com?fileName=C:/Users/smhrd/git/MDS/MDS/src/main/webapp/resources/alarmCapture_h/person33.png" width="230px" height="150px"></div>
                          		<div class="tkdcn">
                                 <div>사람출입</div>
                                 <div>1명 침입</div>
                                 <div>침입시간 : \${res.sah[i].sah_in_at}</div>
                                 </div>
                                </div>
                                
                                 <div class="epqlf">
                                 <div><img src="showImage.com?fileName=C:/Users/smhrd/git/MDS/MDS/src/main/webapp/resources/alarmCapture_h1/person333.png" width="230px" height="150px"></div>
                          		<div class="tkdcn">
                                 <div>사람침입</div>
                                 <div>1명 침입</div>
                                 <div>침입시간 : \${res.sah[i].sah_in_at}</div>
                                 </div>
                                </div>
                                `);
                       }
                    }
                    
                    /*for(var i = 0; i< res.sah.length; i++){
                       if(res.sah[i].sah_in_at.substring(0,10) == today && res.sah[i].sah_in_count != 0 && res.sah[i].sah_out_count != 0){
                    	   $('#epqlftkdcn').append(`
                      			  <div class="epqlf">
                                      <div><img src="showImage.com?fileName=\${res.sah[i].sah_img_link}" width="230px" height="150px"></div>
                               		<div class="tkdcn">
                                      <div>사람침입</div>
                                      <div>\${res.sah[i].sah_in_count}명 침입</div>
                                      <div>침입시간 : \${res.sah[i].sah_in_at}</div>
                                      </div>
                                     </div>
                                `);
                       }
                    }*/
                    
                    $('#page2-content').append(`
                            <button id="epqlfBtn" onclick="$('.epqlf').hide();"style="width: 30px; height: 30px; position: fixed; border-radius: 8px; right: 14rem; top: 8rem; opacity: 0.3;border: solid 0.5px #e9e9e9;box-shadow: inset 0px 0px 4px 2px #c4c3c3b0;background-color: #fff;font-weight:bold;">X</button>
                            `);
                    $('#epqlfBtn').click(function(){
                       $('#epqlfBtn').remove();
                    })
                 }
           })
        },
        
       /*dateClick: function(res){
          console.logr(res));
       }*/
        
    });
    
    calendar.render();
    calendar.updateSize();
   });

 

 

+) 페이지 이동 시 캘린더 layout이 깨지는 오류가 발생

=> 해결 방법 : document.on('click', function(){})을 사용

=> 참고 글 https://stackoverflow.com/questions/18261719/fullcalendar-only-appears-on-reload

 

댓글