코딩기록 저장소 🐕/스스로 프로젝트와 연습

FullCalendar 사용하기(4) 모달창으로 수정

kimkongmom 2024. 4. 23. 20:21

 

 

 

 

시간을 많이 잡아먹었던 수정이었습니다..

fullCalendar를 사용하기때문에 script 부분을 많이 수정해야하더라구요

 

1. 우선 일정을 누르면 모달창을 띄울 수 있게 해줍니다❗

 

부트스트랩에서 가져온 모달창입니다.

수정이기 때문에 컬럼하나하나 name을 적어줘야합니다.

<div class="modal fade" id="editEventModal" tabindex="-1" aria-labelledby="editEventModalLabel" aria-hidden="true">
   <div class="modal-dialog">
      <div class="modal-content">
         <div class="modal-header">
            <h5 class="modal-title" id="editEventModalLabel">일정 수정</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
         </div>
         <div class="modal-body">
            <form id="editEventForm">
               <input type="hidden" id="planNo" name="planNo">
               <div class="form-group">
                  <label for="firstPlan">첫번째 일정</label>
                  <input type="text" class="form-control" name="firstPlan" id="firstPlan">
               </div>
               <div class="form-group">
                  <label for="firstComment">내용</label>
                  <input type="text" class="form-control"  name="firstComment" id="firstComment">
               </div>
               <div class="form-group">
                  <label for="secondPlan">두번째일정</label>
                  <input type="text" class="form-control"  name="secondPlan" id="secondPlan">
               </div>
               <div class="form-group">
                  <label for="secondComment">내용</label>
                  <input type="text" class="form-control" name="secondComment" id="secondComment">
               </div>
               <div class="form-group">
                  <label for="thirdPlan">세번째일정</label>
                  <input type="text" class="form-control"name="thirdPlan" id="thirdPlan">
               </div>
               <div class="form-group">
                  <label for="thirdComment">내용</label>
                  <input type="text" class="form-control"name="thirdComment" id="thirdComment">
               </div>
               <div class="form-group">
                  <label for="startAt">시작 날짜</label>
                  <input type="datetime-local" name="startAt"  class="form-control" id="startAt">
               </div>
               <div>
                  <label for="endAt" class="form-label">끝날짜/시간</label>
                  <input type="datetime-local" name="endAt"  id="endAt" class="form-control">
               </div>
               <div class="modal-footer">
                  <button type="button" class="btn btn-primary" id="edit_btn">저장</button>
               </div>
            </form>
         </div>
      </div>
   </div>
</div>

 

 

2. 누르면 모달창이 나오게 하기

 

전체코드 보다 모달부분을 올렸습니다. 

수정은 기존에 일정들이 보여져야하기 때문에 fullCalendar엣 제공해주는 라이브러리extendedProps를 사용합니다.

extendedProps는 개발자가 이벤트 객체에 추가 정보를 저장하고 필요에 따라 접근할 수 있게 해주는 extendedProps 속성을 제공합니다.

날짜데이터가 좀 애먹었는데요🥲 

JavaScript로 날짜 데이터의 형식을 datetime-local 입력 필드가 요구하는 표준 형식(YYYY-MM-DDTHH:mm)에 맞추어 정확하게 처리해야합니다.

 

oISOString() 메소드는 날짜와 시간을 ISO 8601 형식 (YYYY-MM-DDTHH:mm:ss.sssZ)으로 변환합니다. 이 메소드로 생성된 문자열에서 필요한 부분만 추출(substring(0, 16))하여 날짜와 시간 필드(datetime-local)에 맞는 형식을 만들었습니다.

 

event.end가 존재하지 않을 경우도 있을 수 있기때문에 이 경우에는 시작 시간(event.start)을 종료 시간으로 사용하게 됩니다. 이는 일정이 같은 날에 시작해서 종료되는 경우를 처리하기 위해서 입니다.

eventClick: function(info) {
       var event = info.event;
       var modal = $('#editEventModal');
       modal.find('#firstPlan').val(event.extendedProps.firstPlan); // 첫 번째 계획
       modal.find('#firstComment').val(event.extendedProps.firstComment); // 첫 번째 계획의 코멘트
       modal.find('#secondPlan').val(event.extendedProps.secondPlan); // 두 번째 계획
       modal.find('#secondComment').val(event.extendedProps.secondComment); // 두 번째 계획의 코멘트
       modal.find('#thirdPlan').val(event.extendedProps.thirdPlan); // 세 번째 계획
       modal.find('#thirdComment').val(event.extendedProps.thirdComment); // 세 번째 계획의 코멘트

       // 날짜 데이터 설정
       var formattedStart = event.start.toISOString().substring(0, 16); // "YYYY-MM-DDTHH:mm" 형식
       var formattedEnd = event.end ? event.end.toISOString().substring(0, 16) : formattedStart;

       modal.find('#startAt').val(formattedStart);
       modal.find('#endAt').val(formattedEnd);
       modal.find('#planNo').val(event.extendedProps.planNo);
       modal.modal('show'); // 모달 표시
    },

 

 

요렇게 수정할 수 있도록 나옵니다!

수정페이지

 

 

3. Mapper.xml (update쿼리)

 

where절에서 Plan_NO로 해야합니다. 

User_No했다가 시간 좀 날렸습니다😂

update쿼리가 중복적으로 2번씩 돌아가서 뭐때문인가 했더니 where절 때문이더라구요

PLAN_NO를 사용하도록 수정하여서 특정 일정만을 정확히 타겟팅할 수 있었습니다.

 

<update id="modifyPlan" parameterType="PlanDto">
    UPDATE PLAN_T
        SET START_AT = #{startAt, jdbcType=VARCHAR}
          , END_AT =  #{endAt, jdbcType=VARCHAR}
          , FIRST_PLAN = #{firstPlan, jdbcType=VARCHAR}
          , FIRST_COMMENT = #{firstComment, jdbcType=VARCHAR}
          , SECOND_PLAN = #{secondPlan, jdbcType=VARCHAR}
          , SECOND_COMMENT = #{secondComment, jdbcType=VARCHAR}
          , THIRD_PLAN = #{thirdPlan, jdbcType=VARCHAR}
          , THIRD_COMMENT = #{thirdComment, jdbcType=VARCHAR}
      WHERE PLAN_NO = #{planNo, jdbcType=INTEGER}
</update>

 

 

4. Dao(mapper)

public int modifyPlan(PlanDto plan);

 

 

5. Service

 

insert와 유사하게 작성했습니다 다른점이 있다면 planNo가 들어가야한다는점!

@Override
public int modifyPlan(HttpServletRequest request) {
    int planNo = Integer.parseInt(request.getParameter("planNo"));
    String startAt = request.getParameter("startAt");
    String endAt = request.getParameter("endAt");
    String firstPlan = request.getParameter("firstPlan");
    String firstComment = request.getParameter("firstComment");
    String secondPlan = request.getParameter("secondPlan");
    String secondComment = request.getParameter("secondComment");
    String thirdPlan = request.getParameter("thirdPlan");
    String thirdComment = request.getParameter("thirdComment");

    PlanDto plan = PlanDto.builder()
            .planNo(planNo)
            .startAt(startAt)
            .endAt(endAt)
            .firstPlan(firstPlan)
            .firstComment(firstComment)
            .secondPlan(secondPlan)
            .secondComment(secondComment)
            .thirdPlan(thirdPlan)
            .thirdComment(thirdComment)
            .build();

    int modifyResult = planMapper.modifyPlan(plan);

    return modifyResult;

}

 

 

6. Controller

 

모달창을 ajax를 사용해서 Json으로 받아와야하기때문에 @ResponseBody, produces ="application/json" 필수적으로 적어줍니다.

Map<String, Object> response = new HashMap<>();: 응답을 위한 맵을 생성합니다. 이 맵에는 키와 값의 쌍으로 구성된 데이터가 저장됩니다

modifyResult는 성공여부를 정수값으로 보여줍니다.

@ResponseBody
@PostMapping(value = "/layout/modify.do", produces ="application/json")
public Map<String, Object> updatePlan(HttpServletRequest request, RedirectAttributes redirectAttributes){

    Map<String, Object> response = new HashMap<>();
    int modifyResult = planService.modifyPlan(request);
    response.put("modifyResult", modifyResult);
    return response;
}

 

 

 

7. 수정Ajax🫠(스크립트)

 

우선 #edit_btn을 누르면 실행됩니다.

extendedProps를 사용해서 새로고침하지 않고 바로 수정이 반영되도록 했습니다.

serialize(),를 사용해서 모달창안에 있는 정보를 한꺼번에 보내줍니다.

 

planNo가 null값이 계속 나와서 애를 먹었습니다🥲

모달 html 안에 hidden으로 무조건 넣어줘야합니다.

<input type="hidden" id="planNo" name="planNo">

 

이전 글에있었던 코드입니다. planNo를 찾아줘서 모달창에서 전달이 되게 만들었습니다.

modal.find('#planNo').val(event.extendedProps.planNo);
$(document).on('click', '#edit_btn', function() {
   var events = calendar.getEvents();
   var event = events.find(e => e.id === $('#planNo').val());

   if (event) {
      event.setProp('title', [$('#firstPlan').val(), $('#secondPlan').val(), $('#thirdPlan').val()].filter(Boolean).join(', '));

      // 개별 커멘트 업데이트
      event.setProp('extendedProps.firstComment', $('#firstComment').val());
      event.setProp('extendedProps.secondComment', $('#secondComment').val());
      event.setProp('extendedProps.thirdComment', $('#thirdComment').val());

      event.setStart($('#startAt').val());
      event.setEnd($('#endAt').val());

      $.ajax({
         type: 'POST',
         url: '/layout/modify.do',
         data: $('#editEventForm').serialize(),
         success: function(response) {
            if (response.modifyResult === 1) {
               alert('수정 완료');
               calendar.refetchEvents(); // 캘린더 이벤트를 다시 불러옴
            } else {
               alert('수정 실패');
            }
            $('#editEventModal').modal('hide');
         },
         error: function() {
            alert('서버 오류 발생');
            $('#editEventModal').modal('hide');
         }
      });
   } else {
      alert('수정할 이벤트를 찾을 수 없습니다.');
   }
});

 

 

수정 성공했습니다. 우여곡절이 많았지만 뿌듯한 하루입니다!