JS에서의 AJAX 등과 같은 다양한 처리로 인해, Form 자체의 순수한 기능을 쓸 일은 거의 없어졌습니다. 그럼에도 불구하고 form 의 기능을 어느정도 사용하면 웹 표준을 준수함과 물론, 코드의 유지보수성이 향상되는 효과가 있는데요, 어떻게 작성하면 되는지 그 방법을 한번 공유해보고자 합니다.
<form>
<input type="text" name="name1" />
<input type="text" name="name2" />
...
...
<!-- (Toast UI Grid)외부 라이브러리로 동작하는 input 예시 -->
<div class="tui-datepicker-input tui-datetime-input tui-has-focus">
<input type="text" name="startDate" aria-label="Date" autocomplete="off" />
<span class="tui-ico-date"></span>
<div id="startpicker-container"></div>
</div>
<button type="submit">저장</div>
<button type="reset">리셋</div>
</form>
AJAX 요청을 한 이상, method나 action 속성을 지정할 일이 거의 없어졌습니다. 따라서 form 태그를 구성하지 않고 input과 버튼만으로 구성하는 경우도 종종 볼 수 있는데요, 그럼에도 불구하고 Form 태그를 사용하는것이 저는 옳다고 생각합니다. 그 이유로는
const form = document.querySelector('form selector')
form.addEventListener('submit', handleSubmit);
form.addEventListener('reset', handleReset);
표준에 맞게 HTML 을 구성하면 이렇게 더욱 목적이 분명하게 이벤트를 바인딩 할 수가 있습니다.
function handleSubmit(e) {
e.preventDefault();
var formElement = e.target;
var formData = new FormData(formElement);
var formDataList = Array.from(formData); // IE 미지원
// Validation 검증 - ex) formDataList 를 순회하며 값을 체크한다.
// formData 를 파라미터로 전달하여 AJAX 수행
}
e.target
을 통해 name-value 가 key-value 로 매핑된 객체를 손쉽게 만들 수 있습니다. Form 종류에 상관없이 그 Form 에 맞는 객체를 구성하므로, 유지보수에 탁월합니다. 만약 handleSubmit
이것이 버튼 클릭 이벤트 핸들러였다면, document.querySelector
로 특정 form을 비효율적으로 가져와야 할 것입니다.preventDefault 위치는 아무데나 두셔도 되는데, 주로 읽기 편하라고 맨 위에 두는 편입니다. 아무데나 둬도 되는 이유는 어차피 이벤트가 모두 전파되고 난 마지막(root)에 default 이벤트가 발생하기 때문입니다. 현재 handleSubmit 함수는 이벤트가 모두 전파된 상태도 아닌 상태이기 때문에 코드 어디에서 preventDefault 해도 괜찮은 겁니다.
function handleReset(e) {
// preventDefault 하지 않는다.
// Reset 시 따로 처리하고 싶은 로직 작성(ex. 변경하고 싶은 상태 변경)
// 단순 비우기 reset이 아닌 초기값을 할당하고 싶은 것은 task queue 에 적재하여
// 디폴트 이벤트보다 나중에 실행되도록 한다.
window.setTimeout(customReset)
}
function customReset() { /* ... */ }
preventDefault
는 따로 하지 않았습니다.handleReset
내부에는 디폴트 리셋이 발생하면서 처리하고 싶은 로직을 따로 자유롭게 구성하면 됩니다.setTimeout
을 이용해서 Task Queue 에 적재되어 마지막에 이벤트루프가 실행하도록 설정해야 합니다. 원래는 디폴트 이벤트가 나중에 호출되어 커스텀 로직이 적용되지 않기 때문입니다.이벤트루프에 관한 설명을 nhn meetup 에서 공부하시는 것을 추천드립니다. 매우 설명이 잘 돼있고 중요한 개념입니다!!
어떠한 submit 필요 없이 단순 input 만 필요한 경우에도 form 태그를 구성하는 것을 추천드립니다. 그 이유는 맨 앞서 말한 접근성 측면과 같은 이유와 같습니다.