UNPKG

dkgrid

Version:

A utility class for creating Tabulator grids with JSON configs.

155 lines (141 loc) 6.08 kB
// dkgrid.js /** * DKGridHandler 클래스는 JSON 설정을 기반으로 Tabulator 그리드를 생성하고 관리합니다. * 이 클래스는 인피니트 스크롤, 페이지네이션, 엑셀 다운로드 등의 기능을 포함합니다. */ export class DKGridHandler { constructor(elementId) { this.elementId = elementId; this.table = null; this.loadedData = {}; // constructor에서는 totalDataCount를 초기화하지 않음. this.totalDataCount = 0; } /** * JSON 설정 문자열을 받아 그리드를 생성하거나 업데이트합니다. * @param {string} configJsonText - JSON 형식의 설정 문자열 * @param {number} totalDataCount - 그리드에 표시될 전체 데이터의 수 */ createGrid(configJsonText, totalDataCount) { try { const config = JSON.parse(configJsonText); const parsedConfig = this._parseFunctionsInConfig(config); if (this.table) { this.table.destroy(); this.loadedData = {}; // 그리드 재생성 시 캐시 초기화 } // 외부에서 받은 totalDataCount로 설정 this.totalDataCount = totalDataCount; let paginationOption; if (config.usePaging) { paginationOption = "remote"; } else { paginationOption = false; parsedConfig.height = parsedConfig.height || "400px"; // totalDataCount가 지정되면 paginationSize를 동적으로 설정 parsedConfig.paginationSize = this.totalDataCount; parsedConfig.pagination = false; } this.table = new Tabulator(this.elementId, { ...parsedConfig, dataTree: true, dataTreeParentField: "parentId", pagination: paginationOption, ajaxRequestFunc: this._loadData.bind(this), cellEdited: (cell) => { console.log("셀이 수정되었습니다:", cell.getValue()); } }); console.log("그리드가 JSON 설정에 따라 성공적으로 생성되었습니다."); } catch (error) { console.error("JSON 파싱 또는 그리드 생성 오류:", error); throw new Error("유효하지 않은 JSON 형식입니다."); } } /** * 엑셀 파일로 그리드 데이터를 다운로드합니다. * @param {string} filename - 파일명 */ downloadExcel(filename = "grid_data.xlsx") { if (this.table) { this.table.download("xlsx", filename, { sheetName: "Data" }); } else { console.warn("그리드가 생성되지 않았습니다."); } } /** * 가상의 AJAX 데이터 로드 함수 (내부 메소드) * @private */ _loadData(url, params) { return new Promise((resolve) => { const page = params.page || 1; const size = params.size || 50; this._loadPage(page, size).then(result => { resolve({ last_page: Math.ceil(this.totalDataCount / size), data: result.data }); if (page > 1) this._loadPage(page - 1, size); if (page < Math.ceil(this.totalDataCount / size)) this._loadPage(page + 1, size); }); }); } /** * 실제 데이터 로딩 로직 (캐싱 포함, 내부 메소드) * @private */ _loadPage(page, size) { return new Promise(resolve => { if (this.loadedData[page]) { console.log(`페이지 ${page} 데이터가 캐시에서 로드되었습니다.`); resolve(this.loadedData[page]); return; } const start = (page - 1) * size; const end = Math.min(start + size, this.totalDataCount); const data = []; setTimeout(() => { // 샘플 데이터 생성 for (let i = start; i < end; i++) { data.push({ id: i + 1, name: `User ${i + 1}`, gender: i % 2 === 0 ? "male" : "female", col: ["red", "blue", "green", "orange"][i % 4], dob: `${(i % 28) + 1}/${(i % 12) + 1}/${1980 + (i % 20)}`, parentId: i > 0 && i % 5 === 0 ? Math.floor(Math.random() * i) + 1 : 0, checkbox: i % 3 === 0 }); } const result = { data: data }; this.loadedData[page] = result; console.log(`페이지 ${page} 데이터가 새로 로드되어 캐싱되었습니다.`); resolve(result); }, 500); }); } /** * JSON 설정의 함수 문자열을 실제 함수로 변환 (내부 메소드) * @private */ _parseFunctionsInConfig(obj) { if (typeof obj !== 'object' || obj === null) { return obj; } for (const key in obj) { if (typeof obj[key] === 'string' && obj[key].startsWith('function(')) { try { obj[key] = new Function('e', 'cell', obj[key].replace('function(e, cell)', '')); } catch (e) { console.error(`Error parsing function string for key "${key}":`, e); } } else if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) { obj[key] = this._parseFunctionsInConfig(obj[key]); } else if (Array.isArray(obj[key])) { obj[key].forEach(item => this._parseFunctionsInConfig(item)); } } return obj; } }