홈페이지를 만드는 사람들을 위한 안내서

개요

폼 제출시 화면을 전환하지 않고 AJAX를 사용하면 여러 가지 이점이 있습니다. 한 화면에서 여러 가지 작업을 연속적으로 수행할 수 있고, 처리 시간도 단축되며, 결과 메시지를 별도의 화면이 아닌 alert() 창이나 레이어로 표시할 수 있으므로 사용자 입장에서도 더 편리합니다.

특히 폼 제출 도중 발생한 오류가 화면 전환 후에야 표시되면 내용을 다시 입력해야 하는 불편이 발생합니다. 간단한 폼의 내용은 RXE에서 자동으로 재입력해 줄 수 있으나, 배열이 들어가는 등 구조가 복잡한 폼이거나 자바스크립트를 사용하여 동적으로 생성된 <input>이 있으면 그것까지 모두 재입력해 줄 수 없기 때문에 내용이 날아가 버립니다.

그렇다고 모든 폼을 AJAX로 제출하도록 코드를 작성하려면 상당한 삽질이 필요합니다. 폼 데이터를 추출하여 정리한 후 exec_xml()이나 exec_json() (권장) 함수에 넣어주어야 하지요. <input type="file">이라도 하나 끼어 있으면 이런 함수마저 사용할 수 없으므로 더욱 곤란해집니다. 복잡한 모듈을 만든다면 이 삽질을 폼마다 반복해 주어야 합니다. 스크립트를 꽤 많이 써야 하지요. 그래서 아직도 폼을 제출할 때마다 볼썽사납게 화면이 전환되는 코어 모듈 및 서드파티 자료가 많습니다.

이제 이 삽질을 코어에서 상당 부분 대신 해 줄 수 있게 되었습니다.

방법

아무 폼이든지 rx_ajax 클래스를 추가해 주기만 하면

<form action="{Context::getRequestUri()}" method="post" class="rx_ajax">
    <input type="hidden" name="module" value="mymodule" />
    <input type="hidden" name="act" value="procMymoduleInsertWhatever" />
    ... 중략 ...
</form>

해당 폼은 화면 전환 없이 AJAX로 제출됩니다. 오류가 발생하면 alert() 창으로 표시되고, 제출에 성공하여 redirect URL이 지정되면 해당 화면으로 리다이렉트됩니다.

파일 업로드를 포함한 폼

파일 업로드를 포함한 폼이라도 rx_ajax 클래스만 추가하면 화면 전환 없이 제출할 수 있습니다.

<input type="file">이 포함된 폼은 일반적인 AJAX 요청으로 제출하기 어렵습니다. 따라서 임시로 <iframe>을 생성하고, 해당 <iframe>을 target으로 지정하여 AJAX와 동일하게 백그라운드에서 제출하는 효과를 발휘합니다. (업로더에서도 브라우저 호환성을 위해 종종 사용하는 방식입니다.) 오류 메시지 표시나 redirect URL 처리도 <iframe> 내에서 실행되는 스크립트에 의해 AJAX와 똑같이 이루어지고, 사용이 끝난 <iframe>은 자동으로 삭제됩니다.

<input type="file">의 name 값이 Filedata인 경우 파일 업로드를 포함한 폼으로 간주하지 않습니다. 부모 폼과 무관하게 파일을 직접 업로드하는 RXE 기본 에디터가 Filedata라는 이름을 사용하기 때문입니다. 파일 업로드를 포함한 폼을 제출하려면 Filedata가 아닌 다른 이름을 사용해야 합니다.

기타

폼을 제출받는 controller 쪽에서는 화면 전환이 아닌 AJAX 또는 <iframe> 방식으로 제출된다는 사실에 맞추어 일부 코드 수정이 필요할 수도 있습니다. 그러나 RXE 관례대로 setRedirectUrl()를 사용하거나 오류 메시지를 BaseObject에 넣어 반환하도록 (또는 Rhymix\Framework\Exception을 던지도록) 코딩되어 있다면 대부분은 별다른 수정 없이 작동할 것입니다.

물론 rx_ajax 클래스를 추가하지 않은 기존의 폼에는 아무 영향도 주지 않습니다. 스크립트를 사용할 수 없는 환경에서는 (아직도 그런 게 있나요? ㅋㅋ) 기존과 같이 화면 전환이 발생합니다.

폼에 onsubmit 속성이 있거나 다른 스크립트에서 onsubmit 이벤트를 추가한 경우 이 기능과 충돌할 수 있습니다.

이 방법이 안정화되면 구닥다리 onsubmit="return procFilter(...)" 방식도 상당 부분 대체할 수 있을 것으로 보입니다.


출처 : https://github.com/rhymix/rhymix/pull/1206

도구모음