Refactor Component Handling and Enhance Nested Component Functionality

- Updated ComponentPreview.vue to streamline the rendering of repeating groups by removing unnecessary padding.
- Introduced a new helper function, findContainerRecursively, to locate containers at any nesting level, improving the management of nested components.
- Enhanced the handleSectionDrop, handleUpdateComponent, and handleDeleteComponent functions to utilize the new recursive container finding logic, ensuring consistent behavior across nested structures.
- Improved error handling and logging for component operations, providing better feedback during component manipulation.
- Commented out hover styles in CSS for group items and form components to prevent unintended visual effects during development.
This commit is contained in:
Afiq 2025-08-07 12:18:54 +08:00
parent 917c2acac1
commit a14252a844
2 changed files with 98 additions and 62 deletions

View File

@ -136,7 +136,7 @@
</div> </div>
<!-- Repeating Group Component --> <!-- Repeating Group Component -->
<div v-else-if="component.type === 'repeating-group'" class="py-2"> <div v-else-if="component.type === 'repeating-group'">
<fieldset class="border rounded-md p-4"> <fieldset class="border rounded-md p-4">
<legend class="text-sm font-medium px-2">{{ component.props.label || 'Group' }}</legend> <legend class="text-sm font-medium px-2">{{ component.props.label || 'Group' }}</legend>
@ -1406,8 +1406,8 @@ const onNestedComponentAdd = (event) => {
}; };
const removeFromSection = (sectionId, childIndex) => { const removeFromSection = (sectionId, childIndex) => {
// Actually delete the component from the section (don't move it back to main form) // Find the container at any nesting level
const section = formStore.formComponents.find(comp => comp.id === sectionId); const section = findContainerRecursively(sectionId);
if (section && section.props.children) { if (section && section.props.children) {
const removedComponent = section.props.children.splice(childIndex, 1)[0]; const removedComponent = section.props.children.splice(childIndex, 1)[0];
if (removedComponent) { if (removedComponent) {
@ -1507,7 +1507,32 @@ const deleteNestedComponent = (componentId) => {
} }
}; };
// Helper function to find container at any nesting level
const findContainerRecursively = (containerId, components = formStore.formComponents, childId = null) => {
for (const component of components) {
// Check if this is the target container
if (containerId && component.id === containerId) {
return component;
}
// If searching for parent by child ID, check if this component contains the child
if (childId && component.props.children && Array.isArray(component.props.children)) {
const hasChild = component.props.children.some(child => child.id === childId);
if (hasChild) {
return component;
}
}
// If this component has children, search recursively
if (component.props.children && Array.isArray(component.props.children)) {
const found = findContainerRecursively(containerId, component.props.children, childId);
if (found) {
return found;
}
}
}
return null;
};
const handleSectionDrop = (event, containerId) => { const handleSectionDrop = (event, containerId) => {
event.preventDefault(); event.preventDefault();
@ -1549,8 +1574,8 @@ const handleSectionDrop = (event, containerId) => {
} }
}; };
// Find the target container (section or repeating-group) // Find the target container at any nesting level
const container = formStore.formComponents.find(comp => comp.id === containerId); const container = findContainerRecursively(containerId);
if (container && (container.type === 'form-section' || container.type === 'repeating-group')) { if (container && (container.type === 'form-section' || container.type === 'repeating-group')) {
// Initialize children array if it doesn't exist // Initialize children array if it doesn't exist
if (!container.props.children) { if (!container.props.children) {
@ -1572,6 +1597,8 @@ const handleSectionDrop = (event, containerId) => {
}); });
console.log('Component added to container:', newComponent); console.log('Component added to container:', newComponent);
} else {
console.warn('Container not found or invalid container type:', containerId);
} }
} catch (error) { } catch (error) {
console.error('Error dropping component into container:', error); console.error('Error dropping component into container:', error);
@ -1603,12 +1630,8 @@ const closeNestedSettingsModal = () => {
const saveNestedComponentSettings = (updatedComponent) => { const saveNestedComponentSettings = (updatedComponent) => {
if (!updatedComponent || !selectedNestedComponent.value) return; if (!updatedComponent || !selectedNestedComponent.value) return;
// Find the parent container (section or repeating-group) and update the nested component // Find the parent container at any nesting level
const parentContainer = formStore.formComponents.find(comp => const parentContainer = findContainerRecursively(null, formStore.formComponents, updatedComponent.id);
(comp.type === 'form-section' || comp.type === 'repeating-group') &&
comp.props.children &&
comp.props.children.some(child => child.id === updatedComponent.id)
);
if (parentContainer) { if (parentContainer) {
const childIndex = parentContainer.props.children.findIndex(child => child.id === updatedComponent.id); const childIndex = parentContainer.props.children.findIndex(child => child.id === updatedComponent.id);
@ -1969,9 +1992,9 @@ onMounted(() => {
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
} }
.group-item:hover { /* .group-item:hover {
border-color: #93c5fd; border-color: #93c5fd;
} } */
.repeating-group-container { .repeating-group-container {
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
@ -2018,10 +2041,10 @@ onMounted(() => {
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
} }
.form-component:hover { /* .form-component:hover {
border-color: #93c5fd; border-color: #93c5fd;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
} } */
.component-actions { .component-actions {
opacity: 0; opacity: 0;
@ -2126,10 +2149,10 @@ onMounted(() => {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
.form-component:hover { /* .form-component:hover {
border-color: #93c5fd; border-color: #93c5fd;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
} } */
.component-actions { .component-actions {
position: absolute; position: absolute;

View File

@ -2328,30 +2328,50 @@ const handleSelectNestedComponent = (nestedComponent) => {
console.log('Selected nested component:', nestedComponent); console.log('Selected nested component:', nestedComponent);
}; };
// Helper function to find container at any nesting level
const findContainerRecursively = (containerId, components = formStore.formComponents, childId = null) => {
for (const component of components) {
// Check if this is the target container
if (containerId && component.id === containerId) {
return component;
}
// If searching for parent by child ID, check if this component contains the child
if (childId && component.props.children && Array.isArray(component.props.children)) {
const hasChild = component.props.children.some(child => child.id === childId);
if (hasChild) {
return component;
}
}
// If this component has children, search recursively
if (component.props.children && Array.isArray(component.props.children)) {
const found = findContainerRecursively(containerId, component.props.children, childId);
if (found) {
return found;
}
}
}
return null;
};
const handleUpdateComponent = (updatedComponent) => { const handleUpdateComponent = (updatedComponent) => {
if (!updatedComponent || !updatedComponent.id) return; if (!updatedComponent || !updatedComponent.id) return;
// Check if this is a nested component inside a section // Find the parent container at any nesting level
let foundInSection = false; const parentContainer = findContainerRecursively(null, formStore.formComponents, updatedComponent.id);
// Look for the component in section or repeating-group children if (parentContainer) {
formStore.formComponents.forEach(component => { // Update the nested component
if ((component.type === 'form-section' || component.type === 'repeating-group') && component.props.children) { const childIndex = parentContainer.props.children.findIndex(child => child.id === updatedComponent.id);
const nestedIndex = component.props.children.findIndex(child => child.id === updatedComponent.id); if (childIndex !== -1) {
if (nestedIndex !== -1) { parentContainer.props.children[childIndex] = updatedComponent;
// Update the nested component // Update the entire container to trigger reactivity
component.props.children[nestedIndex] = updatedComponent; formStore.updateComponent(parentContainer);
// Update the entire container to trigger reactivity console.log('Updated nested component in container:', updatedComponent);
formStore.updateComponent(component);
foundInSection = true;
console.log('Updated nested component in container:', updatedComponent);
return;
}
} }
}); } else {
// If not found in sections, update as a main component
// If not found in sections, update as a main component
if (!foundInSection) {
formStore.updateComponent(updatedComponent); formStore.updateComponent(updatedComponent);
} }
}; };
@ -2363,34 +2383,27 @@ const handleMoveComponent = ({ oldIndex, newIndex }) => {
const handleDeleteComponent = (id) => { const handleDeleteComponent = (id) => {
if (!id) return; if (!id) return;
// Check if this is a nested component inside a section // Find the parent container at any nesting level
let foundInSection = false; const parentContainer = findContainerRecursively(null, formStore.formComponents, id);
// Look for the component in section or repeating-group children if (parentContainer) {
formStore.formComponents.forEach(component => { // Remove the nested component
if ((component.type === 'form-section' || component.type === 'repeating-group') && component.props.children) { const childIndex = parentContainer.props.children.findIndex(child => child.id === id);
const nestedIndex = component.props.children.findIndex(child => child.id === id); if (childIndex !== -1) {
if (nestedIndex !== -1) { const deletedComponent = parentContainer.props.children.splice(childIndex, 1)[0];
// Remove the nested component // Update the entire container to trigger reactivity
const deletedComponent = component.props.children.splice(nestedIndex, 1)[0]; formStore.updateComponent(parentContainer);
// Update the entire container to trigger reactivity
formStore.updateComponent(component); // Clear selection if the deleted component was selected
foundInSection = true; if (formStore.selectedComponentId === id) {
formStore.selectedComponent = null;
// Clear selection if the deleted component was selected formStore.selectedComponentId = null;
if (formStore.selectedComponentId === id) {
formStore.selectedComponent = null;
formStore.selectedComponentId = null;
}
console.log('Deleted nested component from container:', deletedComponent);
return;
} }
console.log('Deleted nested component from container:', deletedComponent);
} }
}); } else {
// If not found in sections, delete as a main component
// If not found in sections, delete as a main component
if (!foundInSection) {
formStore.deleteComponent(id); formStore.deleteComponent(id);
} }
}; };