fix: SelectedItemsDetailInput 수정 모드에서 다중 레코드 로드 오류 수정
DynamicComponentRenderer에 selected-items-detail-input groupedData 전달 추가 SelectedItemsDetailInput에서 groupedData 우선 사용하도록 변경 ScreenModal editData 배열 처리 시 formData/selectedData 분리 저장 TextInput 수정 모드에서 채번 규칙 스킵 로직 추가
This commit is contained in:
parent
23c9604672
commit
f8fb7d687e
|
|
@ -175,13 +175,21 @@ export const ScreenModal: React.FC<ScreenModalProps> = ({ className }) => {
|
|||
if (editData) {
|
||||
console.log("📝 [ScreenModal] 수정 데이터 설정:", editData);
|
||||
|
||||
// 🆕 배열인 경우 (그룹 레코드) vs 단일 객체 처리
|
||||
// 🆕 배열인 경우 두 가지 데이터를 설정:
|
||||
// 1. formData: 첫 번째 요소(객체) - 일반 입력 필드용 (TextInput 등)
|
||||
// 2. selectedData: 전체 배열 - 다중 항목 컴포넌트용 (SelectedItemsDetailInput 등)
|
||||
if (Array.isArray(editData)) {
|
||||
console.log(`📝 [ScreenModal] 그룹 레코드 ${editData.length}개 설정`);
|
||||
setFormData(editData as any); // 배열 그대로 전달 (SelectedItemsDetailInput에서 처리)
|
||||
setOriginalData(editData[0] || null); // 첫 번째 레코드를 원본으로 저장
|
||||
const firstRecord = editData[0] || {};
|
||||
console.log(`📝 [ScreenModal] 그룹 레코드 ${editData.length}개 설정:`, {
|
||||
formData: "첫 번째 레코드 (일반 입력 필드용)",
|
||||
selectedData: "전체 배열 (다중 항목 컴포넌트용)",
|
||||
});
|
||||
setFormData(firstRecord); // 🔧 일반 입력 필드용 (객체)
|
||||
setSelectedData(editData); // 🔧 다중 항목 컴포넌트용 (배열) - groupedData로 전달됨
|
||||
setOriginalData(firstRecord); // 첫 번째 레코드를 원본으로 저장
|
||||
} else {
|
||||
setFormData(editData);
|
||||
setSelectedData([editData]); // 🔧 단일 객체도 배열로 변환하여 저장
|
||||
setOriginalData(editData); // 🆕 원본 데이터 저장 (UPDATE 판단용)
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -281,10 +281,12 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
|
|||
// 컴포넌트의 columnName에 해당하는 formData 값 추출
|
||||
const fieldName = (component as any).columnName || component.id;
|
||||
|
||||
// modal-repeater-table은 배열 데이터를 다루므로 빈 배열로 초기화
|
||||
// 다중 레코드를 다루는 컴포넌트는 배열 데이터로 초기화
|
||||
let currentValue;
|
||||
if (componentType === "modal-repeater-table" || componentType === "repeat-screen-modal") {
|
||||
// EditModal에서 전달된 groupedData가 있으면 우선 사용
|
||||
if (componentType === "modal-repeater-table" ||
|
||||
componentType === "repeat-screen-modal" ||
|
||||
componentType === "selected-items-detail-input") {
|
||||
// EditModal/ScreenModal에서 전달된 groupedData가 있으면 우선 사용
|
||||
currentValue = props.groupedData || formData?.[fieldName] || [];
|
||||
} else {
|
||||
currentValue = formData?.[fieldName] || "";
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
|
|||
screenId,
|
||||
...props
|
||||
}) => {
|
||||
// 🆕 groupedData 추출 (DynamicComponentRenderer에서 전달)
|
||||
const groupedData = (props as any).groupedData || (props as any)._groupedData;
|
||||
// 🆕 URL 파라미터에서 dataSourceId 읽기
|
||||
const searchParams = useSearchParams();
|
||||
const urlDataSourceId = searchParams?.get("dataSourceId") || undefined;
|
||||
|
|
@ -225,24 +227,32 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
|
|||
|
||||
// 🆕 모달 데이터를 ItemData 구조로 변환 (그룹별 구조)
|
||||
useEffect(() => {
|
||||
// 🆕 수정 모드: formData에서 데이터 로드 (URL에 mode=edit이 있으면)
|
||||
// 🆕 수정 모드: groupedData 또는 formData에서 데이터 로드 (URL에 mode=edit이 있으면)
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const mode = urlParams.get("mode");
|
||||
|
||||
if (mode === "edit" && formData) {
|
||||
// 🔧 데이터 소스 우선순위: groupedData > formData (배열) > formData (객체)
|
||||
const sourceData = groupedData && Array.isArray(groupedData) && groupedData.length > 0
|
||||
? groupedData
|
||||
: formData;
|
||||
|
||||
if (mode === "edit" && sourceData) {
|
||||
// 배열인지 단일 객체인지 확인
|
||||
const isArray = Array.isArray(formData);
|
||||
const dataArray = isArray ? formData : [formData];
|
||||
const isArray = Array.isArray(sourceData);
|
||||
const dataArray = isArray ? sourceData : [sourceData];
|
||||
|
||||
if (dataArray.length === 0 || (dataArray.length === 1 && Object.keys(dataArray[0]).length === 0)) {
|
||||
console.warn("⚠️ [SelectedItemsDetailInput] formData가 비어있음");
|
||||
console.warn("⚠️ [SelectedItemsDetailInput] 데이터가 비어있음");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`📝 [SelectedItemsDetailInput] 수정 모드 - ${isArray ? "그룹 레코드" : "단일 레코드"} (${dataArray.length}개)`,
|
||||
);
|
||||
console.log("📝 [SelectedItemsDetailInput] formData (JSON):", JSON.stringify(dataArray, null, 2));
|
||||
console.log("📝 [SelectedItemsDetailInput] 데이터 소스:", {
|
||||
fromGroupedData: groupedData && Array.isArray(groupedData) && groupedData.length > 0,
|
||||
dataArray: JSON.stringify(dataArray, null, 2),
|
||||
});
|
||||
|
||||
const groups = componentConfig.fieldGroups || [];
|
||||
const additionalFields = componentConfig.additionalFields || [];
|
||||
|
|
@ -423,7 +433,7 @@ export const SelectedItemsDetailInputComponent: React.FC<SelectedItemsDetailInpu
|
|||
});
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [modalData, component.id, componentConfig.fieldGroups, formData]); // formData 의존성 추가
|
||||
}, [modalData, component.id, componentConfig.fieldGroups, formData, groupedData]); // groupedData 의존성 추가
|
||||
|
||||
// 🆕 Cartesian Product 생성 함수 (items에서 모든 그룹의 조합을 생성)
|
||||
const generateCartesianProduct = useCallback(
|
||||
|
|
|
|||
|
|
@ -51,6 +51,10 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
|
|||
// 숨김 상태 (props에서 전달받은 값 우선 사용)
|
||||
const isHidden = props.hidden !== undefined ? props.hidden : component.hidden || componentConfig.hidden || false;
|
||||
|
||||
// 수정 모드 여부 확인 (originalData가 있으면 수정 모드)
|
||||
const originalData = props.originalData || (props as any)._originalData;
|
||||
const isEditMode = originalData && Object.keys(originalData).length > 0;
|
||||
|
||||
// 자동생성된 값 상태
|
||||
const [autoGeneratedValue, setAutoGeneratedValue] = useState<string>("");
|
||||
|
||||
|
|
@ -99,6 +103,16 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
|
|||
return;
|
||||
}
|
||||
|
||||
// 🆕 수정 모드일 때는 채번 규칙 스킵 (기존 값 유지)
|
||||
if (isEditMode) {
|
||||
console.log("⏭️ 수정 모드 - 채번 규칙 스킵:", {
|
||||
columnName: component.columnName,
|
||||
originalValue: originalData?.[component.columnName],
|
||||
});
|
||||
hasGeneratedRef.current = true; // 생성 완료로 표시하여 재실행 방지
|
||||
return;
|
||||
}
|
||||
|
||||
if (testAutoGeneration.enabled && testAutoGeneration.type !== "none") {
|
||||
// 폼 데이터에 이미 값이 있으면 자동생성하지 않음
|
||||
const currentFormValue = formData?.[component.columnName];
|
||||
|
|
@ -171,7 +185,7 @@ export const TextInputComponent: React.FC<TextInputComponentProps> = ({
|
|||
};
|
||||
|
||||
generateAutoValue();
|
||||
}, [testAutoGeneration.enabled, testAutoGeneration.type, component.columnName, isInteractive]);
|
||||
}, [testAutoGeneration.enabled, testAutoGeneration.type, component.columnName, isInteractive, isEditMode]);
|
||||
|
||||
// 실제 화면에서 숨김 처리된 컴포넌트는 렌더링하지 않음
|
||||
if (isHidden && !isDesignMode) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue