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

View File

@ -2328,30 +2328,50 @@ const handleSelectNestedComponent = (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) => {
if (!updatedComponent || !updatedComponent.id) return;
// Check if this is a nested component inside a section
let foundInSection = false;
// Find the parent container at any nesting level
const parentContainer = findContainerRecursively(null, formStore.formComponents, updatedComponent.id);
// Look for the component in section or repeating-group children
formStore.formComponents.forEach(component => {
if ((component.type === 'form-section' || component.type === 'repeating-group') && component.props.children) {
const nestedIndex = component.props.children.findIndex(child => child.id === updatedComponent.id);
if (nestedIndex !== -1) {
// Update the nested component
component.props.children[nestedIndex] = updatedComponent;
// Update the entire container to trigger reactivity
formStore.updateComponent(component);
foundInSection = true;
console.log('Updated nested component in container:', updatedComponent);
return;
}
if (parentContainer) {
// Update the nested component
const childIndex = parentContainer.props.children.findIndex(child => child.id === updatedComponent.id);
if (childIndex !== -1) {
parentContainer.props.children[childIndex] = updatedComponent;
// Update the entire container to trigger reactivity
formStore.updateComponent(parentContainer);
console.log('Updated nested component in container:', updatedComponent);
}
});
// If not found in sections, update as a main component
if (!foundInSection) {
} else {
// If not found in sections, update as a main component
formStore.updateComponent(updatedComponent);
}
};
@ -2363,34 +2383,27 @@ const handleMoveComponent = ({ oldIndex, newIndex }) => {
const handleDeleteComponent = (id) => {
if (!id) return;
// Check if this is a nested component inside a section
let foundInSection = false;
// Find the parent container at any nesting level
const parentContainer = findContainerRecursively(null, formStore.formComponents, id);
// Look for the component in section or repeating-group children
formStore.formComponents.forEach(component => {
if ((component.type === 'form-section' || component.type === 'repeating-group') && component.props.children) {
const nestedIndex = component.props.children.findIndex(child => child.id === id);
if (nestedIndex !== -1) {
// Remove the nested component
const deletedComponent = component.props.children.splice(nestedIndex, 1)[0];
// Update the entire container to trigger reactivity
formStore.updateComponent(component);
foundInSection = true;
// Clear selection if the deleted component was selected
if (formStore.selectedComponentId === id) {
formStore.selectedComponent = null;
formStore.selectedComponentId = null;
}
console.log('Deleted nested component from container:', deletedComponent);
return;
if (parentContainer) {
// Remove the nested component
const childIndex = parentContainer.props.children.findIndex(child => child.id === id);
if (childIndex !== -1) {
const deletedComponent = parentContainer.props.children.splice(childIndex, 1)[0];
// Update the entire container to trigger reactivity
formStore.updateComponent(parentContainer);
// Clear selection if the deleted component was selected
if (formStore.selectedComponentId === id) {
formStore.selectedComponent = null;
formStore.selectedComponentId = null;
}
console.log('Deleted nested component from container:', deletedComponent);
}
});
// If not found in sections, delete as a main component
if (!foundInSection) {
} else {
// If not found in sections, delete as a main component
formStore.deleteComponent(id);
}
};