SPA AJAX Request With JQuery
이전에 만들었던 버전은 핸들바의 script 태그를 이용해 메인 html에 여러 페이지의 템플릿을 숨겨두고 요청에 따라 템플릿을 보여주었는데 이번에는 네비게이터를 만들었다.
href의 #해시 요청과 button의 클릭 이벤트 발생시 hash를 바꿔주어 hashchange 이벤트가 발생하면
navigator에서 hash의 url을 확인하고 템플릿을 꺼내고 필요한 AJAX 요청을 한다.
function navigate() {
const hash = window.location.hash;
const path = hash.substring(1);
let html = "";
hash는 #로 시작하므로 지저분한 #을 떼주고 path만 남도록 substring으로 정리해주었다.
템플릿을 받을 html 변수를 생성
if (path == '/guest_main') {
html = guest_main();
} else if (path == '/guest_list') {
ajaxRequest(GUEST_LIST.method,GUEST_LIST.url,function(responseJsonObject){
html = guest_list(responseJsonObject);
$('#content').html(html);//????
});
}
이런식으로 path를 구분하여 main으로 보낼지 list로 보낼지 결정한다.
문제는 list의 ajax 요청이다.
ajax 요청이라하면 요청을 하고 응답을 받는 동안 쓰레드가 계속 돌아야하는데
ajax 요청의 콜백함수에서 guest_list의 템플릿에 json 데이터를 핸들바로 바인딩하여 완성된 템플릿을 받아 html에 초기화 시킬때까지 기다리게 된다.
이문제는 추후 promise 객체로 해결한다.
여기서 guest_main, guest_list 함수는
import { guest_main } from "./template-guest-main.js";
import { guest_write_form } from "./template-guest-write-form.js";
import { guest_list } from "./template-guest-list.js";
import { ajaxRequest } from "./request.js";
import {GUEST_DETAIL,GUEST_MODIFY_ACTION,GUEST_MODIFY_FORM,
GUEST_REMOVE_ACTION,GUEST_LIST,GUEST_WRITE_ACTION} from "./request-url.js";
template을 반환하는 함수를 가진 js 모듈을 import한 것이다.
템플릿 함수는 대략 이런 구조를 가진다.
let htmlTemplate = `
<table >
<tbody>
<tr>
<td>번호</td>
<td>제목</td>
<td>이름</td>
<td>날짜</td>
</tr>
{{#each data}}
<tr class="guest_item">
<td>{{guest_no}}</td>
<td>
<a href="#/guest_detail/{{guest_no}}" class="user guest_item_a">{{guest_title}}
</a>
</td>
<td>{{toUpper guest_name}}</td>
<td>{{substring guest_date 0 10}}</td>
</tr>
{{/each}}
</tbody>
</table>`;
let bindTemplate = Handlebars.compile(htmlTemplate);
let resultTemplate = bindTemplate(responseJsonObject);
return resultTemplate;
html 템플릿 텍스트를 Handlebars.compile 하여 만들 bindTemplate 함수에 Ajax 요청에 대한 응답으로 받은 responseJsonObject를 넣어준뒤 완성된 템플릿인 resultTemplate을 만들어반환한다.
else if(path.startsWith('/guest_modify_form/')){
const guest_no = path.substring(path.lastIndexOf('/')+1);
ajaxRequest(GUEST_MODIFY_FORM.method,GUEST_MODIFY_FORM.url.replace('@guest_no',guest_no),function(responseJsonObject){
html = guest_modify_form(responseJsonObject);
$('#content').html(html);
})
}
수정폼에선 기존의 데이터를 가져와야하기 때문에 guest_no가 필요하다
guest_no는 view(detail)에서 가져온다.
<input type="button" data-navigate="/guest_modify_form/{{data.[0].guest_no}}" value="수정" >
view 버튼 중에 수정 버튼은 data-navigate라는 custom attribute를 가지고 있다.
버튼을 클릭하면 클릭이벤트가 발생하는데 이 클릭이벤트가 발생하면 해쉬체인지 이벤트가 발생하도록 해준다.
$(document).on('click',function(e){
if(e.target.getAttribute('data-navigate')){
window.location.hash=e.target.getAttribute('data-navigate');
}
});
data-navigate의 /guest_modify_form/guest_no 를 가져올수 있게된다.
navigate에서는 여기서 가져온 guest_no로 restController의 guests/guest_no에 필요한 guest_no를 채울수 있게된다.
else if(path.startsWith('/guest_modify_action/')){
const guest_no = path.substring(path.lastIndexOf('/')+1);
데이터 검증 생략
let sendJsonObject = {
guest_no: $('#guest_modify_form [name="guest_no"]').val(),
guest_date: "",
guest_name: $('#guest_modify_form [name="guest_name"]').val(),
guest_email: $('#guest_modify_form [name="guest_email"]').val(),
guest_homepage: $('#guest_modify_form [name="guest_homepage"]').val(),
guest_title: $('#guest_modify_form [name="guest_title"]').val(),
guest_content: $('#guest_modify_form [name="guest_content"]').val()
};
ajaxRequest(GUEST_MODIFY_ACTION.method,GUEST_MODIFY_ACTION.url.replace('@guest_no',guest_no),function(responseJsonObject){
if (responseJsonObject.status == 1) {
//쓰기 성공시 HashChange 이벤트 발생
window.location.hash='/guest_detail/'+guest_no;
} else {
alert(responseJsonObject.msg);
}
},sendJsonObject)
}
ajax request가 성공하면
window.location.hash를 변경해주어 guest_detail 템플릿을 뿌리도록 이벤트를 발생시킨다.