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)
댓글 남기기