fix: Improve TableListComponent and UniversalFormModalComponent for better data handling
- Updated TableListComponent to use flex-nowrap and overflow-hidden for better badge rendering. - Enhanced UniversalFormModalComponent to maintain the latest formData using a ref, preventing stale closures during form save events. - Improved data merging logic in UniversalFormModalComponent to ensure accurate updates and maintain original data integrity. - Refactored buttonActions to streamline table section data collection and merging, ensuring proper handling of modified and original data during save operations.
This commit is contained in:
@@ -247,6 +247,10 @@ export function UniversalFormModalComponent({
|
||||
|
||||
// 폼 데이터 상태
|
||||
const [formData, setFormData] = useState<FormDataState>({});
|
||||
// formDataRef: 항상 최신 formData를 유지하는 ref
|
||||
// React 상태 업데이트는 비동기적이므로, handleBeforeFormSave 등에서
|
||||
// 클로저의 formData가 오래된 값을 참조하는 문제를 방지
|
||||
const formDataRef = useRef<FormDataState>({});
|
||||
const [, setOriginalData] = useState<Record<string, any>>({});
|
||||
|
||||
// 반복 섹션 데이터
|
||||
@@ -398,18 +402,19 @@ export function UniversalFormModalComponent({
|
||||
console.log("[UniversalFormModal] beforeFormSave 이벤트 수신");
|
||||
console.log("[UniversalFormModal] 설정된 필드 목록:", Array.from(configuredFields));
|
||||
|
||||
// formDataRef.current 사용: blur+click 동시 처리 시 클로저의 formData가 오래된 문제 방지
|
||||
const latestFormData = formDataRef.current;
|
||||
|
||||
// 🆕 시스템 필드 병합: id는 설정 여부와 관계없이 항상 전달 (UPDATE/INSERT 판단용)
|
||||
// - 신규 등록: formData.id가 없으므로 영향 없음
|
||||
// - 편집 모드: formData.id가 있으면 메인 테이블 UPDATE에 사용
|
||||
if (formData.id !== undefined && formData.id !== null && formData.id !== "") {
|
||||
event.detail.formData.id = formData.id;
|
||||
console.log(`[UniversalFormModal] 시스템 필드 병합: id =`, formData.id);
|
||||
if (latestFormData.id !== undefined && latestFormData.id !== null && latestFormData.id !== "") {
|
||||
event.detail.formData.id = latestFormData.id;
|
||||
console.log(`[UniversalFormModal] 시스템 필드 병합: id =`, latestFormData.id);
|
||||
}
|
||||
|
||||
// UniversalFormModal에 설정된 필드만 병합 (채번 규칙 포함)
|
||||
// 외부 formData에 이미 값이 있어도 UniversalFormModal 값으로 덮어씀
|
||||
// (UniversalFormModal이 해당 필드의 주인이므로)
|
||||
for (const [key, value] of Object.entries(formData)) {
|
||||
for (const [key, value] of Object.entries(latestFormData)) {
|
||||
// 설정에 정의된 필드 또는 채번 규칙 ID 필드만 병합
|
||||
const isConfiguredField = configuredFields.has(key);
|
||||
const isNumberingRuleId = key.endsWith("_numberingRuleId");
|
||||
@@ -432,17 +437,13 @@ export function UniversalFormModalComponent({
|
||||
}
|
||||
|
||||
// 🆕 테이블 섹션 데이터 병합 (품목 리스트 등)
|
||||
// 참고: initializeForm에서 DB 로드 시 __tableSection_ (더블),
|
||||
// handleTableDataChange에서 수정 시 _tableSection_ (싱글) 사용
|
||||
for (const [key, value] of Object.entries(formData)) {
|
||||
// 싱글/더블 언더스코어 모두 처리
|
||||
// formDataRef.current(= latestFormData) 사용: React 상태 커밋 전에도 최신 데이터 보장
|
||||
for (const [key, value] of Object.entries(latestFormData)) {
|
||||
// _tableSection_ 과 __tableSection_ 모두 원본 키 그대로 전달
|
||||
// buttonActions.ts에서 DB데이터(__tableSection_)와 수정데이터(_tableSection_)를 구분하여 병합
|
||||
if ((key.startsWith("_tableSection_") || key.startsWith("__tableSection_")) && Array.isArray(value)) {
|
||||
// 저장 시에는 _tableSection_ 키로 통일 (buttonActions.ts에서 이 키를 기대)
|
||||
const normalizedKey = key.startsWith("__tableSection_")
|
||||
? key.replace("__tableSection_", "_tableSection_")
|
||||
: key;
|
||||
event.detail.formData[normalizedKey] = value;
|
||||
console.log(`[UniversalFormModal] 테이블 섹션 병합: ${key} → ${normalizedKey}, ${value.length}개 항목`);
|
||||
event.detail.formData[key] = value;
|
||||
console.log(`[UniversalFormModal] 테이블 섹션 병합: ${key}, ${value.length}개 항목`);
|
||||
}
|
||||
|
||||
// 🆕 원본 테이블 섹션 데이터도 병합 (삭제 추적용)
|
||||
@@ -457,6 +458,22 @@ export function UniversalFormModalComponent({
|
||||
event.detail.formData._originalGroupedData = originalGroupedData;
|
||||
console.log(`[UniversalFormModal] 원본 그룹 데이터 병합: ${originalGroupedData.length}개`);
|
||||
}
|
||||
|
||||
// 🆕 부모 formData의 중첩 객체(modalKey)도 최신 데이터로 업데이트
|
||||
// onChange(setTimeout)가 아직 부모에 전파되지 않았을 수 있으므로 직접 업데이트
|
||||
for (const parentKey of Object.keys(event.detail.formData)) {
|
||||
const parentValue = event.detail.formData[parentKey];
|
||||
if (parentValue && typeof parentValue === "object" && !Array.isArray(parentValue)) {
|
||||
const hasTableSection = Object.keys(parentValue).some(
|
||||
(k) => k.startsWith("_tableSection_") || k.startsWith("__tableSection_"),
|
||||
);
|
||||
if (hasTableSection) {
|
||||
event.detail.formData[parentKey] = { ...latestFormData };
|
||||
console.log(`[UniversalFormModal] 부모 중첩 객체 업데이트: ${parentKey}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("beforeFormSave", handleBeforeFormSave as EventListener);
|
||||
@@ -482,10 +499,11 @@ export function UniversalFormModalComponent({
|
||||
|
||||
// 테이블 섹션 데이터 설정
|
||||
const tableSectionKey = `_tableSection_${tableSection.id}`;
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
[tableSectionKey]: _groupedData,
|
||||
}));
|
||||
setFormData((prev) => {
|
||||
const newData = { ...prev, [tableSectionKey]: _groupedData };
|
||||
formDataRef.current = newData;
|
||||
return newData;
|
||||
});
|
||||
|
||||
groupedDataInitializedRef.current = true;
|
||||
}, [_groupedData, config.sections]);
|
||||
@@ -965,6 +983,7 @@ export function UniversalFormModalComponent({
|
||||
}
|
||||
|
||||
setFormData(newFormData);
|
||||
formDataRef.current = newFormData;
|
||||
setRepeatSections(newRepeatSections);
|
||||
setCollapsedSections(newCollapsed);
|
||||
setActivatedOptionalFieldGroups(newActivatedGroups);
|
||||
@@ -1132,6 +1151,9 @@ export function UniversalFormModalComponent({
|
||||
console.log(`[연쇄 드롭다운] 부모 ${columnName} 변경 → 자식 ${childField} 초기화`);
|
||||
}
|
||||
|
||||
// ref 즉시 업데이트 (React 상태 커밋 전에도 최신 데이터 접근 가능)
|
||||
formDataRef.current = newData;
|
||||
|
||||
// onChange는 렌더링 외부에서 호출해야 함 (setTimeout 사용)
|
||||
if (onChange) {
|
||||
setTimeout(() => onChange(newData), 0);
|
||||
|
||||
Reference in New Issue
Block a user