export default class PageMaker {
constructor(page = 1, perPageNum = 10) {
this.page = page; // 현재 페이지
this.perPageNum = perPageNum; // 페이지당 항목 수
this.pageStart = 0; // 페이지 시작 인덱스
this.totalCount = 0; // 전체 항목 수
this.startPage = 1; // 시작 페이지
this.endPage = 1; // 끝 페이지
this.prev = false; // 이전 페이지 여부
this.next = false; // 다음 페이지 여부
this.displayPageNum = 10; // 하단 페이지 번호 표시 수
this.tempEndPage = 1; // 임시 끝 페이지
this.calcData(); // 페이지 계산 초기화
}
// 페이지 설정
setPage(page) {
if (page <= 0) {
this.page = 1;
} else {
this.page = page;
}
this.pageStart = (this.page - 1) * this.perPageNum;
}
// 페이지당 항목 수 설정
setPerPageNum(perPageNum) {
if (perPageNum <= 0 || perPageNum > 100) {
this.perPageNum = 10;
} else {
this.perPageNum = perPageNum;
}
this.pageStart = (this.page - 1) * this.perPageNum;
}
// 전체 항목 수 설정 및 페이지 계산
setTotalCount(totalCount) {
this.totalCount = totalCount;
this.calcData();
}
// 페이지 계산
calcData() {
this.endPage = Math.ceil(this.page / this.displayPageNum) * this.displayPageNum;
this.startPage = this.endPage - this.displayPageNum + 1;
this.tempEndPage = Math.ceil(this.totalCount / this.perPageNum);
if (this.endPage > this.tempEndPage) {
this.endPage = this.tempEndPage;
}
this.prev = this.startPage > 1;
this.next = this.endPage * this.perPageNum < this.totalCount;
}
// 쿼리 문자열 생성
makeQuery(page) {
const params = new URLSearchParams();
params.append('page', page);
params.append('perPageNum', this.perPageNum);
return params.toString();
}
// 페이지네이션 HTML 생성
bootStrapPagingHTML(url) {
let html = "<ul class='pagination'>";
if (this.prev) {
html += `<li><a href='${url}?${this.makeQuery(1)}'>처음</a></li>`;
}
if (this.prev) {
html += `<li><a href='${url}?${this.makeQuery(this.startPage - 1)}'>«</a></li>`;
}
for (let i = this.startPage; i <= this.endPage; i++) {
const active = this.page === i ? "class='active'" : "";
html += `<li ${active}><a href='${url}?${this.makeQuery(i)}'>${i}</a></li>`;
}
if (this.next) {
html += `<li><a href='${url}?${this.makeQuery(this.endPage + 1)}'>»</a></li>`;
}
if (this.next) {
html += `<li><a href='${url}?${this.makeQuery(this.tempEndPage)}'>마지막</a></li>`;
}
html += "</ul>";
return html;
}
}
타입스트립트 적용
export default class PageMaker {
private page: number;
private perPageNum: number;
private pageStart: number;
private totalCount: number;
private startPage: number;
private endPage: number;
private prev: boolean;
private next: boolean;
private displayPageNum: number;
private tempEndPage: number;
constructor(page: number = 1, perPageNum: number = 10) {
this.page = page; // 현재 페이지
this.perPageNum = perPageNum; // 페이지당 항목 수
this.pageStart = 0; // 페이지 시작 인덱스
this.totalCount = 0; // 전체 항목 수
this.startPage = 1; // 시작 페이지
this.endPage = 1; // 끝 페이지
this.prev = false; // 이전 페이지 여부
this.next = false; // 다음 페이지 여부
this.displayPageNum = 10; // 하단 페이지 번호 표시 수
this.tempEndPage = 1; // 임시 끝 페이지
this.calcData(); // 페이지 계산 초기화
}
setPage(page: number): void {
if (page <= 0) {
this.page = 1;
} else {
this.page = page;
}
this.pageStart = (this.page - 1) * this.perPageNum;
}
setPerPageNum(perPageNum: number): void {
if (perPageNum <= 0 || perPageNum > 100) {
this.perPageNum = 10;
} else {
this.perPageNum = perPageNum;
}
this.pageStart = (this.page - 1) * this.perPageNum;
}
setTotalCount(totalCount: number): void {
this.totalCount = totalCount;
this.calcData();
}
private calcData(): void {
this.endPage =
Math.ceil(this.page / this.displayPageNum) * this.displayPageNum;
this.startPage = this.endPage - this.displayPageNum + 1;
this.tempEndPage = Math.ceil(this.totalCount / this.perPageNum);
if (this.endPage > this.tempEndPage) {
this.endPage = this.tempEndPage;
}
this.prev = this.startPage > 1;
this.next = this.endPage * this.perPageNum < this.totalCount;
}
getPageStart(): number {
return this.pageStart;
}
getPerPageNum(): number {
return this.perPageNum;
}
private makeQuery(page: number): string {
const params = new URLSearchParams();
params.append("page", page.toString());
params.append("perPageNum", this.perPageNum.toString());
return params.toString();
}
bootStrapPagingHTML(url: string): string {
let html = "<ul class='pagination'>";
if (this.prev) {
html += `<li><a href='${url}?${this.makeQuery(1)}'>처음</a></li>`;
}
if (this.prev) {
html += `<li><a href='${url}?${this.makeQuery(
this.startPage - 1
)}'>«</a></li>`;
}
for (let i = this.startPage; i <= this.endPage; i++) {
const active = this.page === i ? "class='active'" : "";
html += `<li ${active}><a href='${url}?${this.makeQuery(
i
)}'>${i}</a></li>`;
}
if (this.next) {
html += `<li><a href='${url}?${this.makeQuery(
this.endPage + 1
)}'>»</a></li>`;
}
if (this.next) {
html += `<li><a href='${url}?${this.makeQuery(
this.tempEndPage
)}'>마지막</a></li>`;
}
html += "</ul>";
return html;
}
}
주요 사항:
- 생성자: 클래스 생성자에서 페이지와 페이지당 항목 수를 초기화합니다.
- setPage 및 setPerPageNum: 페이지와 페이지당 항목 수를 설정하며, 이를 통해 pageStart를 계산합니다.
- setTotalCount: 전체 항목 수를 설정하고 페이지 정보를 계산합니다.
- calcData: 페이지 계산 로직을 처리합니다.
- makeQuery: URL 쿼리 문자열을 생성합니다.
- bootStrapPagingHTML: 페이지네이션 HTML을 생성합니다.
이 JavaScript 클래스는 Java 페이지 처리 클래스의 기능을 JavaScript로 구현하여 페이지네이션을 처리할 수 있도록 합니다.
예제 코드
// 페이지네이션 설정
const pageMaker = new PageMaker();
// 전체 항목 수 설정 (예: 123개의 항목이 있다고 가정)
pageMaker.setTotalCount(123);
// 페이지당 항목 수 설정 (예: 10개 항목을 한 페이지에 표시)
pageMaker.setPerPageNum(10);
// 현재 페이지 설정 (예: 5페이지)
pageMaker.setPage(5);
// 페이지네이션 HTML 생성
const url = "/items"; // 페이지네이션 링크의 기본 URL
const paginationHTML = pageMaker.bootStrapPagingHTML(url);
// 생성된 페이지네이션 HTML을 웹 페이지에 삽입
document.getElementById("pagination").innerHTML = paginationHTML;
다음과 같이 사용할것
const pageMaker = new PageMaker(Number(page), Number(pageSize));
pageMaker.setTotalCount(totalItems);
pageMaker.setPage(Number(page));
const pageStart = pageMaker.getPageStart();
const perPageNum = pageMaker.getPerPageNum();
console.log(" 현재 페이지 :", page, pageStart, perPageNum);
Express 샘플
import db from "@/lib/mysqldb";
import PageMaker from "@/util/pageMaker";
export interface PropertyDTO {
num: number;
propertyId: number;
ownerId: number;
name: string;
type: string;
description: string;
address1: string;
address2: string;
address3: string;
zipcode: string;
beds: number;
baths: number;
squareFeet: number;
nightlyRate: number;
weeklyRate: number;
monthlyRate: number;
sellerName: string;
sellerEmail: string;
sellerPhone: string;
isFeatured: boolean;
amenities: string[];
images: string[];
regTime: Date;
updateTime: Date;
}
const SELECT_PROPERTY_QUERY = `
SELECT
p.property_id AS propertyId,
p.owner_id AS ownerId,
p.name,
p.type,
p.description,
p.address1,
p.address2,
p.address3,
p.zipcode,
p.beds,
p.baths,
p.square_feet AS squareFeet,
p.nightly_rate AS nightlyRate,
p.weekly_rate AS weeklyRate,
p.monthly_rate AS monthlyRate,
p.seller_name AS sellerName,
p.seller_email AS sellerEmail,
p.seller_phone AS sellerPhone,
p.is_featured AS isFeatured,
p.reg_time AS regTime,
p.update_time AS updateTime,
GROUP_CONCAT(DISTINCT pa.amenity ORDER BY pa.amenity SEPARATOR ', ') AS amenities,
GROUP_CONCAT(DISTINCT pi.images ORDER BY pi.images SEPARATOR ', ') AS images
FROM property p
LEFT JOIN property_amenities pa ON p.property_id = pa.property_id
LEFT JOIN property_images pi ON p.property_id = pi.property_id
GROUP BY p.property_id
`;
export async function selectPropertiesTotalModel(keyword: string | undefined, searchType: string | undefined): Promise<number> {
let query = `SELECT count(*) as total FROM
(
${SELECT_PROPERTY_QUERY}
) RR WHERE RR.propertyId > 0`;
const params: (string | number)[] = [];
let {query: q, params: p} = searchQuery(query, params, keyword, searchType);
const [rows] = await db.query(q, p);
return rows[0].total as number;
}
//전체 목록
export async function selectSearchAllPropertiesModel(
keyword: string | undefined,
searchType: string | undefined,
page: string | undefined,
pageSize: string | undefined
){
const totalItems = await selectPropertiesTotalModel(keyword, searchType);
if (!totalItems) return null;
if(!page) page = "1";
if(!pageSize) pageSize = "6";
// console.log(" 2 selectSearchAllPropertiesModel : ", keyword, searchType, page, pageSize);
const pageMaker = new PageMaker(Number(page), Number(pageSize));
pageMaker.setTotalCount(totalItems);
pageMaker.setPage(Number(page));
const pageStart = pageMaker.getPageStart();
const perPageNum = pageMaker.getPerPageNum();
console.log(" 현재 페이지 :", page, pageStart, perPageNum);
let query = `SELECT RRR.* FROM (
SELECT @rownum := @rownum + 1 AS num, RR.* FROM
(
${SELECT_PROPERTY_QUERY}
) RR ,
(SELECT @rownum :=0) AS r
WHERE RR.propertyId > 0`;
const params: (string | number)[] = [];
const { query: q, params: p } = searchQuery(query, params, keyword, searchType);
const finalQuery = `${q} ORDER BY RR.propertyId ASC
) RRR ORDER by RRR.num DESC
LIMIT ? , ?`;
p.push(pageStart, perPageNum);
const [rows] = await db.query(finalQuery, p);
let rowsData: PropertyDTO[] | null = null;
if (rows && Array.isArray(rows)) {
rowsData = rows.map(property => {
property.amenities = property.amenities ? property.amenities.toString().split(',').map((item: string) => item.trim()) : [];
property.images = property.images ? property.images.toString().split(',').map((item: string) => item.trim()) : [];
return property;
});
}
if (!rowsData) {
console.error("No properties found or failed to process the data.");
return null; // or you might want to return an empty array instead of null
}
return { rowsData, pageMaker };
}
function searchQuery(query:string,params:(string | number)[], keyword:string|undefined, searchType:string|undefined): {query:string, params:(string | number)[]} {
if (keyword) {
query += `
AND (address1 LIKE ? OR address2 LIKE ? OR address3 LIKE ?
OR zipcode LIKE ? OR name LIKE ?)`;
params.push(`%${keyword}%`, `%${keyword}%`, `%${keyword}%`, `%${keyword}%`, `%${keyword}%`);
if (searchType && searchType !== "All") {
query += ` AND RR.type = ?`;
params.push(searchType);
}
}
return {query ,params};
}
HTML 구조
HTML 페이지에 pagination이라는 ID를 가진 요소를 추가합니다. 페이지네이션 HTML이 이 요소에 삽입됩니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pagination Example</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
<div id="pagination"></div>
<script src="path/to/your/PageMaker.js"></script>
<script>
// 페이지네이션 사용 예
const pageMaker = new PageMaker();
pageMaker.setTotalCount(123);
pageMaker.setPerPageNum(10);
pageMaker.setPage(5);
const url = "/items";
const paginationHTML = pageMaker.bootStrapPagingHTML(url);
document.getElementById("pagination").innerHTML = paginationHTML;
</script>
</body>
</html>
주요 단계
- PageMaker 객체 생성: 페이지네이션 기능을 처리하기 위한 PageMaker 객체를 생성합니다.
- 항목 수 설정: 전체 항목 수를 설정합니다.
- 페이지당 항목 수 설정: 한 페이지에 표시할 항목 수를 설정합니다.
- 현재 페이지 설정: 현재 페이지를 설정합니다.
- 페이지네이션 HTML 생성: 페이지네이션 링크가 포함된 HTML 문자열을 생성합니다.
- HTML 삽입: 생성된 페이지네이션 HTML을 웹 페이지의 적절한 위치에 삽입합니다.
이 예제는 기본적인 페이지네이션을 구현하며, 실제 웹 애플리케이션에서는 서버에서 데이터와 페이지 정보를 가져와서 이 클래스를 활용할 수 있습니다.
넥스트 페이징 처리
https://macaronics.net/m04/react/view/2268












댓글 ( 0)
댓글 남기기