st: fix: 그리드 mergeCell sort 오류 & ESLint 에러 수정
This commit is contained in:
@@ -62,7 +62,7 @@ function createNumberComparer(dp: RealGridDataProviderComparer): (field: string
|
||||
};
|
||||
}
|
||||
|
||||
const CompactDataGrid = ({ columnInfo, fixedColumns, showHeaderCheckbox = false, rowData, setRowData }: DataGridProps) => {
|
||||
const CompactDataGrid = ({ columnInfo, fixedColumns, showHeaderCheckbox = false, rowData }: DataGridProps) => {
|
||||
const { columns, columnLayout } = columnInfo;
|
||||
const gridRef = useRef<RealGridReact>(null);
|
||||
|
||||
@@ -255,7 +255,7 @@ const CompactDataGrid = ({ columnInfo, fixedColumns, showHeaderCheckbox = false,
|
||||
autoGenerateField={true}
|
||||
layout={columnLayout}
|
||||
rows={rowData}
|
||||
onInitialized={(grid) => {
|
||||
onInitialized={() => {
|
||||
const dp = gridRef.current?.dataProvider as { setFields?: (fields: unknown[]) => void } | undefined;
|
||||
if (dp?.setFields) {
|
||||
dp.setFields(buildFieldsFromColumns(columns));
|
||||
|
||||
@@ -112,12 +112,14 @@ function createOnSortingHandler(
|
||||
),
|
||||
];
|
||||
// mergeCells: true인 컬럼 찾기 (시군구 등) - 그룹 필드로 사용
|
||||
// 시군구를 우선으로 찾고, 없으면 첫 번째 mergeCells 컬럼 사용
|
||||
// 시군구(sggNm) 우선, 없으면 행정구역명(admdstNm), 없으면 첫 번째 mergeCells 컬럼
|
||||
const mergeCellCols = columns.filter(
|
||||
(c) => c.mergeCells === true && c.fieldName,
|
||||
);
|
||||
const mergeCellCol =
|
||||
mergeCellCols.find((c) => c.fieldName === "gugun") || mergeCellCols[0];
|
||||
mergeCellCols.find((c) => c.fieldName === "sggNm") ||
|
||||
mergeCellCols.find((c) => c.fieldName === "admdstNm") ||
|
||||
mergeCellCols[0];
|
||||
const groupField = mergeCellCol?.fieldName || null;
|
||||
const orderByField = "displayYear"; // 고정값 또는 설정 가능하게 할 수 있음
|
||||
const hasMergeCells = mergeCellCols.length > 0;
|
||||
@@ -148,7 +150,8 @@ function createOnSortingHandler(
|
||||
const col = columns.find(
|
||||
(c) => c.fieldName === sortField || c.name === sortField,
|
||||
);
|
||||
if (!col || col.sortdisable) return true;
|
||||
// sortdisable 컬럼은 정렬 불가(클릭 무시)
|
||||
if (!col || col.sortdisable) return false;
|
||||
|
||||
// mergeCells: true인 컬럼이 없으면 RealGrid 기본 정렬 사용
|
||||
if (!hasMergeCells || !groupField) return true;
|
||||
@@ -173,6 +176,7 @@ function createOnSortingHandler(
|
||||
if (orig && setRows) {
|
||||
setRows(orig);
|
||||
setRowData(orig);
|
||||
(g as { refresh?: () => void }).refresh?.();
|
||||
}
|
||||
sortDirRef.current[sortField] = "none";
|
||||
return false;
|
||||
@@ -191,11 +195,13 @@ function createOnSortingHandler(
|
||||
);
|
||||
setRows?.(sorted);
|
||||
setRowData(sorted);
|
||||
// 데이터 변경 후 merge 재적용
|
||||
(g as { refresh?: () => void }).refresh?.();
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
/** sortPreserveGroupOrder: 그룹 간에는 sortField로 정렬, 그룹 내에서는 원본 순서 유지. */
|
||||
/** sortPreserveGroupOrder: 그룹 간에는 sortField로 정렬, 그룹 내에서는 원본 순서 유지(구분 포함). */
|
||||
function sortRowsGroupPreserving(
|
||||
rows: Record<string, string | number>[],
|
||||
sortField: string,
|
||||
@@ -852,6 +858,7 @@ const DataGrid = ({
|
||||
...(col.mergeCells && {
|
||||
mergeRule: { criteria: "value" as const },
|
||||
}),
|
||||
sortable: !col.sortdisable,
|
||||
};
|
||||
|
||||
if (col.footer) {
|
||||
|
||||
@@ -57,96 +57,96 @@ function toNum(v: unknown): number {
|
||||
}
|
||||
|
||||
/** 헤더에 정렬 화살표 표시 (CSS 방식) */
|
||||
function updateHeaderSortIndicator(
|
||||
gridView: {
|
||||
columnByIndex?: (i: number) => { fieldName?: string; name?: string } | undefined;
|
||||
columnByName?: (name: string) => { fieldName?: string; name?: string } | undefined;
|
||||
getColumn?: (i: number) => { fieldName?: string; name?: string } | undefined;
|
||||
getElement?: () => HTMLElement | null;
|
||||
container?: HTMLElement;
|
||||
},
|
||||
columns: { fieldName?: string; name: string }[],
|
||||
sortDir: Record<string, "asc" | "desc" | "none">,
|
||||
gridElement?: HTMLElement | null
|
||||
) {
|
||||
try {
|
||||
// 그리드 DOM 요소 찾기
|
||||
let gridEl: HTMLElement | null = null;
|
||||
if (gridElement) {
|
||||
gridEl = gridElement;
|
||||
} else if (gridView.getElement) {
|
||||
gridEl = gridView.getElement();
|
||||
} else if (gridView.container) {
|
||||
gridEl = gridView.container;
|
||||
} else {
|
||||
// 폴백: 모든 그리드 중에서 찾기
|
||||
const allGrids = document.querySelectorAll('.rg-grid, [data-grid-id]');
|
||||
if (allGrids.length > 0) {
|
||||
// 활성 탭의 그리드를 찾기 위해 TabsContent 내부의 그리드 찾기
|
||||
const activeTabContent = document.querySelector('[data-state="active"]')?.closest('[role="tabpanel"]');
|
||||
if (activeTabContent) {
|
||||
gridEl = activeTabContent.querySelector('.rg-grid, [data-grid-id]') as HTMLElement;
|
||||
}
|
||||
if (!gridEl && allGrids.length === 1) {
|
||||
gridEl = allGrids[0] as HTMLElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
// function updateHeaderSortIndicator(
|
||||
// gridView: {
|
||||
// columnByIndex?: (i: number) => { fieldName?: string; name?: string } | undefined;
|
||||
// columnByName?: (name: string) => { fieldName?: string; name?: string } | undefined;
|
||||
// getColumn?: (i: number) => { fieldName?: string; name?: string } | undefined;
|
||||
// getElement?: () => HTMLElement | null;
|
||||
// container?: HTMLElement;
|
||||
// },
|
||||
// columns: { fieldName?: string; name: string }[],
|
||||
// sortDir: Record<string, "asc" | "desc" | "none">,
|
||||
// gridElement?: HTMLElement | null
|
||||
// ) {
|
||||
// try {
|
||||
// // 그리드 DOM 요소 찾기
|
||||
// let gridEl: HTMLElement | null = null;
|
||||
// if (gridElement) {
|
||||
// gridEl = gridElement;
|
||||
// } else if (gridView.getElement) {
|
||||
// gridEl = gridView.getElement();
|
||||
// } else if (gridView.container) {
|
||||
// gridEl = gridView.container;
|
||||
// } else {
|
||||
// // 폴백: 모든 그리드 중에서 찾기
|
||||
// const allGrids = document.querySelectorAll('.rg-grid, [data-grid-id]');
|
||||
// if (allGrids.length > 0) {
|
||||
// // 활성 탭의 그리드를 찾기 위해 TabsContent 내부의 그리드 찾기
|
||||
// const activeTabContent = document.querySelector('[data-state="active"]')?.closest('[role="tabpanel"]');
|
||||
// if (activeTabContent) {
|
||||
// gridEl = activeTabContent.querySelector('.rg-grid, [data-grid-id]') as HTMLElement;
|
||||
// }
|
||||
// if (!gridEl && allGrids.length === 1) {
|
||||
// gridEl = allGrids[0] as HTMLElement;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!gridEl) return;
|
||||
// if (!gridEl) return;
|
||||
|
||||
columns.forEach((col) => {
|
||||
if (!col.fieldName && !col.name) return;
|
||||
// columns.forEach((col) => {
|
||||
// if (!col.fieldName && !col.name) return;
|
||||
|
||||
const fieldName = col.fieldName || col.name;
|
||||
const direction = sortDir[fieldName] || sortDir[col.name] || "none";
|
||||
if (direction === "none") return;
|
||||
// const fieldName = col.fieldName || col.name;
|
||||
// const direction = sortDir[fieldName] || sortDir[col.name] || "none";
|
||||
// if (direction === "none") return;
|
||||
|
||||
// 헤더 셀 찾기 (fieldName 또는 name으로)
|
||||
const headerCells = gridEl.querySelectorAll('.rg-header-cell, [class*="header"], .rg-header');
|
||||
let targetCell: HTMLElement | null = null;
|
||||
// // 헤더 셀 찾기 (fieldName 또는 name으로)
|
||||
// const headerCells = gridEl.querySelectorAll('.rg-header-cell, [class*="header"], .rg-header');
|
||||
// let targetCell: HTMLElement | null = null;
|
||||
|
||||
headerCells.forEach((cell) => {
|
||||
const el = cell as HTMLElement;
|
||||
const text = el.textContent?.trim();
|
||||
const colName = col.name;
|
||||
const colFieldName = col.fieldName;
|
||||
// 헤더 텍스트와 컬럼 이름이 일치하는지 확인
|
||||
if (text && (
|
||||
text === colName ||
|
||||
text === colFieldName ||
|
||||
text.includes(colName) ||
|
||||
(colFieldName && text.includes(colFieldName))
|
||||
)) {
|
||||
targetCell = el;
|
||||
}
|
||||
});
|
||||
// headerCells.forEach((cell) => {
|
||||
// const el = cell as HTMLElement;
|
||||
// const text = el.textContent?.trim();
|
||||
// const colName = col.name;
|
||||
// const colFieldName = col.fieldName;
|
||||
// // 헤더 텍스트와 컬럼 이름이 일치하는지 확인
|
||||
// if (text && (
|
||||
// text === colName ||
|
||||
// text === colFieldName ||
|
||||
// text.includes(colName) ||
|
||||
// (colFieldName && text.includes(colFieldName))
|
||||
// )) {
|
||||
// targetCell = el;
|
||||
// }
|
||||
// });
|
||||
|
||||
if (!targetCell) return;
|
||||
// if (!targetCell) return;
|
||||
|
||||
const headerCell = targetCell as HTMLElement;
|
||||
// const headerCell = targetCell as HTMLElement;
|
||||
|
||||
// 기존 화살표 제거
|
||||
const existingIndicator = headerCell.querySelector(".rg-sort-indicator") as HTMLElement | null;
|
||||
if (existingIndicator) {
|
||||
existingIndicator.remove();
|
||||
}
|
||||
// // 기존 화살표 제거
|
||||
// const existingIndicator = headerCell.querySelector(".rg-sort-indicator") as HTMLElement | null;
|
||||
// if (existingIndicator) {
|
||||
// existingIndicator.remove();
|
||||
// }
|
||||
|
||||
// 화살표 추가
|
||||
const indicator = document.createElement("span");
|
||||
indicator.className = "rg-sort-indicator";
|
||||
indicator.textContent = direction === "asc" ? "▲" : "▼";
|
||||
indicator.style.marginLeft = "4px";
|
||||
indicator.style.fontSize = "10px";
|
||||
indicator.style.color = "#666";
|
||||
indicator.style.display = "inline-block";
|
||||
indicator.style.verticalAlign = "middle";
|
||||
headerCell.appendChild(indicator);
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn("updateHeaderSortIndicator error:", e);
|
||||
}
|
||||
}
|
||||
// // 화살표 추가
|
||||
// const indicator = document.createElement("span");
|
||||
// indicator.className = "rg-sort-indicator";
|
||||
// indicator.textContent = direction === "asc" ? "▲" : "▼";
|
||||
// indicator.style.marginLeft = "4px";
|
||||
// indicator.style.fontSize = "10px";
|
||||
// indicator.style.color = "#666";
|
||||
// indicator.style.display = "inline-block";
|
||||
// indicator.style.verticalAlign = "middle";
|
||||
// headerCell.appendChild(indicator);
|
||||
// });
|
||||
// } catch (e) {
|
||||
// console.warn("updateHeaderSortIndicator error:", e);
|
||||
// }
|
||||
// }
|
||||
|
||||
/** onSorting: mergeCells: true인 컬럼이 있으면 그룹 내 순서 유지 정렬, 없으면 RealGrid 기본 정렬 */
|
||||
function createOnSortingHandler(
|
||||
@@ -154,13 +154,13 @@ function createOnSortingHandler(
|
||||
setRowData: React.Dispatch<React.SetStateAction<Record<string, string | number>[]>>,
|
||||
sortDirRef: { current: Record<string, "asc" | "desc" | "none"> },
|
||||
originalRowsRef: { current: Record<string, Record<string, string | number>[]> },
|
||||
findGridElement?: () => HTMLElement | null
|
||||
_findGridElement?: () => HTMLElement | null
|
||||
) {
|
||||
const fieldNames = [...new Set(columns.map((c) => c.fieldName).filter((x): x is string => typeof x === "string"))];
|
||||
// mergeCells: true인 컬럼 찾기 (시군구 등) - 그룹 필드로 사용
|
||||
// 시군구를 우선으로 찾고, 없으면 첫 번째 mergeCells 컬럼 사용
|
||||
const mergeCellCols = columns.filter((c) => c.mergeCells === true && c.fieldName);
|
||||
const mergeCellCol = mergeCellCols.find((c) => c.fieldName === 'gugun') || mergeCellCols[0];
|
||||
const mergeCellCol = mergeCellCols.find((c) => c.fieldName === 'sggNm') || mergeCellCols[0];
|
||||
const groupField = mergeCellCol?.fieldName || null;
|
||||
const orderByField = 'displayYear'; // 고정값 또는 설정 가능하게 할 수 있음
|
||||
const hasMergeCells = mergeCellCols.length > 0;
|
||||
|
||||
Reference in New Issue
Block a user