1. html 코드는 간단하다.
thead와 tbody에 id를 준 뒤에 내용이 바뀔 때마다 pagereload를 실행하도록 하였다.
<table id="data-table-combine" class="table table-striped table-bordered table-hover table-td-valign-middle text-center">
<thead id="memDiv1">
</thead>
<tbody id="memDiv2">
</tbody>
</table>
2. script쪽에서 먼저 pagereload함수를 페이지가 켜지자마자 실행되도록 한다. 이전에 선언한 pagingObject를 인자로 담고 인자에 따라 리스트가 표시되도록 설정했다.( 어느 schema를 조회할지, 어떤 url로 보낼것인지 등)
var pagingObject = new Object({name : "Car",url : "/ajax/car_list", CNU : "{{company.CNU}}", array : [], sort : "CA", page : 0, postNum : 10, pageNum : 5, startpage : 0, endpage : 0, search: "", searchtext : "", searchdate : ""});
$(document).ready(function() {
pagereload(pagingObject); // 첫 화면 페이지 로드
});
- pagingObject
name |
사용할 스키마의 이름 |
url |
Ajax URL |
CNU |
사업자번호( 페이징과 무관) |
array |
백엔드에서 가져온 list |
sort |
정렬 옵션 |
page |
현재 페이지 번호 |
postNum |
게시될 데이터의 갯수 |
pageNum |
게시될 페이지번호의 갯수 |
startpage |
시작 페이지 |
endpage |
끝 페이지 |
search |
검색 옵션 |
searchtext |
검색 옵션(문자) |
searchdate |
검색 옵션(날짜) |
3. pagereload 함수는 변경사항이 있을 때마다 (검색하거나 정렬하거나 페이지가 바뀌거나 등) 실행이 될것이며, 그 때마다 리스트의 내용을 바꿔주는 함수이다.
function pagereload(Object) {
$("input:checkbox[name='allck']").prop("checked", false);
$("input:checkbox[name='ck']").prop("checked", false);
$.ajax({
url: Object.url,
type: "POST",
async: false,
dataType: 'json',
data: {
CID : Object.CID,
CNU : Object.CNU,
sort : Object.sort,
search : Object.search,
searchtext : Object.searchtext,
searchdate : Object.searchdate
}
}).done(function (data) {
if(data.result == true) {
Object.array = data.pagelist; // 전체 리스트
Object.startpage = Math.floor((Object.page) / Object.pageNum) * Object.pageNum;
Object.endpage = Object.startpage + Object.pageNum;
var postNum = Object.postNum; // 게시될 페이지 숫자
var pageNum = Object.pageNum; // 페이지 번호의 갯수
var totalPage = Math.ceil(Object.array.length/Object.postNum); // 전체 페이지의 갯수
if (Object.endpage > totalPage) { // 끝 페이지가 총 페이지 수보다 많다면 같게끔 처리
Object.endpage = totalPage;
}
//tr 초기화
$("#data-table-combine > tbody > tr").remove();
//페이지 넘버 박스 초기화
$("#pagebox *").remove();
if(Object.name == "Company") {
companylist_condition(Object);
}
else if (Object.name == "Car") {
carlist_condition(Object);
}
var insertTr = " ";
insertTr += "<a href='javascript:;' onclick=pageDoubleBtn('left',pagingObject,'basic') class='btn btn-primary mr-1 px-2'><i class='fas fa-angle-double-left'></i></a>";
insertTr += "<a href='javascript:;' onclick=pageBtn('left',pagingObject,'basic') class='btn btn-primary mr-1 px-2'><i class='fas fa-angle-left'></i></a>";
for(var i = Object.startpage; i < Object.endpage; i ++) {
if(Object.page == i)
insertTr += "<input type='button' onclick=pagebutton(pagingObject,"+ i +",'basic') value ='"+ (i+1) +"' class='btn btn-white mr-1 px-2 text-primary' style='background-color: #00acac; color: white !important;' >";
else
insertTr += "<input type='button' onclick=pagebutton(pagingObject,"+ i +",'basic') value ='"+ (i+1) +"' class='btn btn-white mr-1 px-2 text-primary' >";
}
insertTr += "<a href='javascript:;' onclick=pageBtn('right',pagingObject,'basic') class='btn btn-primary mr-1 px-2'><i class='fas fa-angle-right'></i></a>";
insertTr += "<a href='javascript:;' onclick=pageDoubleBtn('right',pagingObject,'basic') class='btn btn-primary mr-1 px-2'><i class='fas fa-angle-double-right'></i></a>";
$("#pagebox").append(insertTr);
$("#pagebox").show();
}
else if (data.result == "nothing") {
$("#searchtext").val('');
$("#searchdatetext1").val('');
$("#searchdatetext2").val('');
$("#memDiv2").empty();
Object.array = [];
if(Object.name == "Company") {
companylist_condition(Object);
}
else if (Object.name == "Car") {
carlist_condition(Object);
}
}
else {
$("#searchdatetext1").val('');
$("#searchdatetext2").val('');
}
});
}
4. 리스트에 따라 xx_condition 이라는 함수를 만들어서 리스트 내용을 채워준다.
ex}carlist_condition
// 차량 리스트
var carlist_condition = function (Object) {
var num = Object.array.length;
var insertTr = ""; // 채워넣을 HTML 초기화
var indexcount = 1; // 인덱스번호 초기화
$("#memDiv1").empty();
insertTr += "<tr>";
insertTr += "<th id ='allcheck' width='1%'>";
insertTr += "<input type='checkbox' name='allck' class='neHeros' value='' onChange='allCheckedBox(this);'/>";
insertTr += "</th>";
insertTr += "<th width='2.5%'></th>";
insertTr += "<th width='10%' name='ANA'>"+i18nconvert("agent_branch")+"<a href='javascript:sortList(pagingObject,ANA);'><i id = 'ANA' class='float-right mx-1 fas fa-lg fa-fw m-t-3 ";
if(Object.sort == "ANA-2")
insertTr += "fa-sort-up'></a></i></th>";
else if(Object.sort == "ANA")
insertTr += "fa-sort-down'></a></i></th>";
else
insertTr += "fa-sort'></a></i></th>";
insertTr += "</th>";
insertTr += "<th width='28%' name='CN'>"+i18nconvert("CN")+"<a href='javascript:sortList(pagingObject,CN);'><i id = 'CN' class='float-right mx-1 fas fa-lg fa-fw m-t-3 ";
if(Object.sort == "CN-2")
insertTr += "fa-sort-up'></a></i></th>";
else if(Object.sort == "CN")
insertTr += "fa-sort-down'></a></i></th>";
else
insertTr += "fa-sort'></a></i></th>";
insertTr += "<th width='30%'name='CPN'>"+i18nconvert("CPN")+"<a href='javascript:sortList(pagingObject,CPN);'><i id = 'CPN' class='float-right mx-1 fas fa-lg fa-fw m-t-3 ";
if(Object.sort == "CPN-2")
insertTr += "fa-sort-up'></a></i></th>";
else if(Object.sort == "CPN")
insertTr += "fa-sort-down'></a></i></th>";
else
insertTr += "fa-sort'></a></i></th>";
insertTr += "<th width='27.5%'name='CA'>"+i18nconvert("CA")+"<a href='javascript:sortList(pagingObject,CA);'><i id = 'CA' class='float-right mx-1 fas fa-lg fa-fw m-t-3 ";
if(Object.sort == "CA-2")
insertTr += "fa-sort-up'></a></i></th>";
else if(Object.sort == "CA")
insertTr += "fa-sort-down'></a></i></th>";
else
insertTr += "fa-sort'></a></i></th>";
insertTr += "<th width='1%'></th>";
insertTr += "</tr>";
$("#memDiv1").append(insertTr);
insertTr = "";
for (var i = ( Object.postNum * Object.page) ; i < ( Object.postNum * Object.page) + Object.postNum ; i ++) { // 현재 페이지의 번호에 맞는 리스트 뽑아서 출력 (0 ~ 9, 10 ~ 19)
if( Object.array.length != 0) {
if( Object.array[i]) {
insertTr += "<tr>";
insertTr += "<td class='with-btn' nowrap>";
insertTr += "<input id='ck' type='checkbox' name ='ck' class='neHeros' value="+ Object.array[i].CN +" onChange='eachCheckedBox(this);'/>";
insertTr += "</td>";
insertTr += "<td class='font-weight-bold'>"+(num - ( Object.page*10)) +" </td>";
insertTr += "<td><a href='javascript:;' class='text-black' onclick=searchNow(pagingObject,'ANA','"+ Object.array[i].ANA +"')><u>"+ Object.array[i].ANA +"</u></a></td>";
insertTr += "<td>"+ Object.array[i].CN+"</td>";
if(! Object.array[i].CPN){
insertTr+="<td>"+"N/A"+"</td><td>";
}
else {
insertTr += "<td>"+ Object.array[i].CPN+"</td><td>";
}
if ( (moment( Object.array[i].CA).format('DD')) == moment().format('DD') )
{
insertTr += moment( Object.array[i].CA).format('HH:mm');
}
else {
insertTr += moment( Object.array[i].CA).format('YYYY-MM-DD');
}
insertTr += "</td><td class='with-btn' nowrap>";
insertTr += "<a href='javascript:;' id = 'carid' onclick='car_editone(this);' data-type='show' name='"+ Object.array[i]._id +"' data-carnum='"+ Object.array[i].CN +"' class='btn btn-sm btn-primary width-60 m-r-2 edit-btn'>"+i18nconvert("modify")+"</a>";
insertTr += "<input type='button' value='"+i18nconvert("delete")+"' onclick=delete_one(this,'/car/ajax/car_deleteone') class='btn btn-sm btn-white width-60' name =' "+ Object.array[i].CN +"'></td> ";
insertTr += "</tr>";
num -= indexcount;
}
}
else {
insertTr += "<tr>";
insertTr += "<td colspan='10'>No Data</td>";
insertTr += "</tr>";
break;
}
}
$("#memDiv2").append(insertTr);
};
5. 백엔드에서 옵션에 관한 내용들을 받고, 데이터를 클라이언트로 보내준다.
( searchCNU는 미들웨어에서 이 사이트에서 필요한 내용을 실행한 것이므로 무시하고 원하는 데이터를 얻을 수 있게끔 하시면 됩니다. )
//car list
router.post('/car_list', isNotLoggedIn, DataSet, agentDevide, async function(req, res, next) {
const CNU = req.body.CNU;
var sort = req.body.sort;
var search = req.body.search;
var searchtext = req.body.searchtext;
var searchdate = req.body.searchdate;
var sortText = "";
var sortNum = 0;
var cars = new Object;
// company list에서 접속한 것인지 확인
if(CNU.includes("#") == true) {
req.searchCNU = CNU.split("#")[0]; // '#' 을 잘라
}
else {
req.searchCNU = req.searchCNU; // 기존 middleware에서 받아온 본사,지점 CNU 그대로 다시 담음
}
// 정렬 기능
if(sort.includes('-') == true) {
sortText = sort.split('-')[0];
sortNum = 1;
}
else {
sortText = sort;
sortNum = -1;
}
try {
var doc = {
lookup : { from : "Company", localField : "CNU", foreignField : "CNU", as : "ANA" } ,
unwind : "$ANA",
match : {},
project : { CN : '$CN', CPN : '$CPN', CA : '$CA', ANA : '$ANA.ANA' },
sort : { [sortText]: sortNum }
}
if(cars.length == 0) {
return res.send({ result : "nothing" });
}
else {
if (searchdate) {
var searchtext2 = searchdate.split("~");
if(search == "ANA") {
doc.match = { "CNU": { $regex: req.searchCNU }, "ANA.ANA" : {$regex:searchtext}, "CA" : { $gte: new Date(searchtext2[0]+"T00:00:00.000Z"), $lt: new Date(searchtext2[1]+"T23:59:59.999Z") } };
}
else if(search == "CN") {
doc.match = { "CNU": { $regex: req.searchCNU }, "CN" : {$regex:searchtext}, "CA" : { $gte: new Date(searchtext2[0]+"T00:00:00.000Z"), $lt: new Date(searchtext2[1]+"T23:59:59.999Z") } };
}
else if(search == "CPN") {
doc.match = { "CNU": { $regex: req.searchCNU }, "CPN" : {$regex:searchtext}, "CA" : { $gte: new Date(searchtext2[0]+"T00:00:00.000Z"), $lt: new Date(searchtext2[1]+"T23:59:59.999Z") } };
}
else {
doc.match = { "CNU": { $regex: req.searchCNU }, "CA" : { $gte: new Date(searchtext2[0]+"T00:00:00.000Z"), $lt: new Date(searchtext2[1]+"T23:59:59.999Z") } } ;
}
}
else {
if(search == "ANA") {
doc.match = { "CNU": { $regex: req.searchCNU }, "ANA.ANA" : {$regex:searchtext} };
}
else if (search =="CN") {
doc.match = { "CNU": { $regex: req.searchCNU }, "CN" : {$regex:searchtext} };
}
else if (search =="CPN") {
doc.match = { "CNU": { $regex: req.searchCNU }, "CPN" : {$regex:searchtext} };
}
else {
doc.match ={ "CNU": { $regex: req.searchCNU } };
}
}
}
cars = await modelQuery(QUERY.Aggregate,COLLECTION_NAME.Car,doc,{});
if(cars.length == 0) {
return res.send({ result : "nothing" });
}
var carlist = [];
if(cars.length) {
for(var i = 0; i < cars.length; i ++) {
carlist[i] = cars[i];
}
}
res.send({ result: true, pagelist : carlist });
} catch(err) {
console.error(err);
next(err);
}
});
try catch 문에서 나는 mongoose aggregate라는 쿼리를 사용했지만, 각자 용도에 맞게 쿼리문을 사용하면 된다.
몽고 쿼리에 관한 내용은 차후에 올리도록 하겠다.