[jQuery] .val()로는 안 되는 Datepicker 값 복원 문제와 해결법

2025. 5. 6. 16:21Project

프론트엔드에서 날짜 유효성 검사를 진행했다.

잘못된 입력값을 alert()으로 경고한 뒤 이전 값으로 되돌리는 로직으로 수행하였다.

 

처음에는 val로 복원을 진행하였지만, 복원 값이 무시되는 문제가 발생하였다.

이를 해결하기 위해 .datepicker('update', value)를 진행하였다.

 

왜 val만으로는 이런 문제가 발생되고 어떠한 방식으로 문제가 해결되었는지 남기고자 한다.

 

1. 날짜 범위 확인 후 alert 설정

$('#startDate, #endDate, #productTypeListSelectBox').on('change', function () {
	const selectedRows = machineListTable.getData("selected");
	const start = $("#startDate").val();
	const end = $("#endDate").val();

	if (start && end && start > end) {
		alert("시작일은 종료일보다 클 수 없습니다.");
		return;
	}

	if (selectedRows.length > 0) {
		proSumYearSelect(selectedRows[0].equipment_INFO_CODE, start, end);
	}
});

 

해당 로직은 다음과 같이 진행된다.

  • 두 값이 모두 존재할 때만 비교하도록 조건 추가 (start && end)
  • startDate > endDate일 경우 alert 발생
  • 실행 중단 (return)

하지만, alert("시작일은 종료일보다 클 수 없습니다."); 후 값이 변하면 안되지만 값이 변하고 있었다.

 

2. 이전 값을 저장하는 로직

때문에 alert가 발생되면 변경되지 않도록 하기 위해 focus 시 이전 값을 저장하는 로직을 진행하였다.

$(document).ready(function() {
	
	let prevDates = {
	    startDate: $("#startDate").val(),
	    endDate: $("#endDate").val()
	};
	
	// focus 시 이전 값 저장
	$('#startDate, #endDate').on('focus', function () {
	    prevDates[this.id] = $(this).val();
	    console.log("focus값", prevDates)
	});
	
	$('#startDate, #endDate, #productTypeListSelectBox').on('change', function() {
		const selectedRows = machineListTable.getData("selected");
		const start = $("#startDate").val();
		const end = $("#endDate").val();
		
		if (start && end && start > end) {
			alert("시작일은 종료일보다 클 수 없습니다.");
			$(this).val(prevDates[this.id]);
			console.log("change값", prevDates[this.id])
			return;
		}
		
		if (selectedRows.length > 0) {
			proSumYearSelect(selectedRows[0].equipment_INFO_CODE, start, end);
		}
	});
})

 

 

  • prevDates 객체를 활용해 startDate, endDate 모두 저장 및 복구
  • this.id를 이용해 어떤 input인지 구분

하지만 이 경우 역시 복원 값이 무시되었다.

 

이러한 이유는 change 이벤트 후 이미 값이 바뀐 상태에서 검사하고 있기 때문에,

alert()을 띄워도 잘못된 값이 입력된 상태로 남게 되기 때문이다.

즉, alert 이후 console에서는 변화 전 값이 찍히지만, 이후 값이 변하게 된다.

 

datepicker는 내부적으로 다음 순서로 동작한다. 

1. 사용자가 날짜를 선택 → change 이벤트 발생
2. 작성한 $('#startDate').on('change', ...) 실행
3. 그 직후, datepicker 내부 로직이 실행되어 input 값을 다시 조정 (포맷 보정, 렌더링 동기화 등)

즉, .val()로 예전 값을 제공해도 그 다음 줄에서 datepicker가 다시 값을 바꿔버린다.

// 내부 동작 예시 (jQuery UI Datepicker 기준)
this.input.val(formattedDate); // 사용자가 클릭한 날짜로 다시 셋팅됨

 

3. jQuery .val() 호출 직후 브라우저가 강제로 datepicker 내부 값을 덮어씌움

해결 방법: .datepicker('update', value)를 사용해 복원 진행

 

datepicker는 change 이벤트가 끝난 직후 자체적으로 내부 상태를 다시 렌더링 진행

이 타이밍이 jQuery .val()로 값을 복원하는 것보다 늦게 실행되도록 설정

$('#startDate, #endDate, #productTypeListSelectBox').on('change', function () {
	const selectedRows = machineListTable.getData("selected");
	const start = $("#startDate").val();
	const end = $("#endDate").val();

	if (start && end && start > end) {
		alert("시작일은 종료일보다 클 수 없습니다.");

		const prevVal = prevDates[this.id];
		$(this).val(prevVal);
		$(this).datepicker('setDate', prevVal);	 // 내부 상태 + UI까지 모두 복원
		return;
	}

	if (selectedRows.length > 0) {
		proSumYearSelect(selectedRows[0].equipment_INFO_CODE, start, end);
	}
});

 

+) 참고사항

  • .datepicker('update', ...)는 Bootstrap Datepicker 기준이며,
  • jQuery UI Datepicker는 .datepicker('setDate', ...)를 사용

 


문제 요약

$(this).val(prevVal);
 

이렇게 입력 필드의 값을 복원해도,

datepicker는 change 이벤트가 끝난 직후에 자신의 내부 로직에 따라 다시 값을 덮어쓴다.
즉, .val()로 복원한 값이 datepicker에 의해 덮어씌워지면서 사라지는 현상이 발생한다.


문제 원인

Bootstrap Datepicker나 jQuery UI Datepicker 등은 내부적으로 다음과 같은 구조로 동작합니다:

  1. 사용자가 날짜를 변경하면:
    • 브라우저에서 change 이벤트가 발생
    • → on('change', handler)가 먼저 실행됨
  2. 그 후에
    • datepicker 라이브러리 내부에서 입력값 포맷 처리 또는 자동 날짜 보정 로직이 동작함
    • → 이 과정에서 필드에 새로운 값이 설정됨 (복원한 값이 덮임)

그래서 단순 .val()로는 복원이 보장되지 않음.


해결 방법

$(this).datepicker('setDate', prevVal);
datepicker가 change 이벤트 이후 내부적으로 값을 다시 렌더링하기 때문에, 단순 .val()만으로는 이전 값을 복원할 수 없다.

datepicker('setDate', ...)는 해당 라이브러리 내부 상태(날짜 객체)와 input UI를 동시에 지정한 값으로 바꾸는 메서드이다.

즉, .val()은 DOM 입력값만 바꾸는 것이고,
.datepicker('setDate', ...)는 UI와 내부 상태 모두를 동기화하는 것으로 

라이브러리 내부에서 자동으로 실행되고 있는 datepicker의 값을 다시 복원 해주어야 한다.