diff --git a/components/ComponentPreview.vue b/components/ComponentPreview.vue index d9d04d7..d70abb2 100644 --- a/components/ComponentPreview.vue +++ b/components/ComponentPreview.vue @@ -547,7 +547,7 @@ const props = defineProps({ } }); -const emit = defineEmits(['select-nested-component']); +const emit = defineEmits(['select-nested-component', 'form-data-updated']); // Get access to the form builder store const formStore = useFormBuilderStore(); @@ -606,6 +606,37 @@ onMounted(() => { } } } + + // Initialize repeating groups + if (props.component.type === 'repeating-group') { + const groupName = props.component.props.name; + if (groupName) { + // Get current groups or initialize empty array + const currentGroups = safeGetField(groupName, formStore.previewFormData); + + // If no groups exist and minItems is specified, create initial groups + if ((!currentGroups || currentGroups.length === 0) && props.component.props.minItems > 0) { + const initialGroups = []; + const minItems = props.component.props.minItems || 1; + + for (let i = 0; i < minItems; i++) { + const newGroup = {}; + + // Add fields from configuration + if (props.component.props.fields) { + props.component.props.fields.forEach(field => { + newGroup[field.name] = ''; + }); + } + + initialGroups.push(newGroup); + } + + const updatedData = { ...formStore.previewFormData, [groupName]: initialGroups }; + formStore.updatePreviewFormData(updatedData); + } + } + } }); // Watch for changes to component props, especially defaultItems @@ -622,6 +653,39 @@ watch(() => props.component.props.defaultItems, (newDefaultItems, oldDefaultItem } }, { deep: true, immediate: true }); +// Watch for changes to repeating group props +watch(() => props.component.props.minItems, (newMinItems, oldMinItems) => { + if (props.component.type === 'repeating-group') { + const groupName = props.component.props.name; + if (!groupName) return; + + const currentGroups = safeGetField(groupName, formStore.previewFormData); + const minItems = newMinItems || 1; + + // If current groups are fewer than minItems, add missing groups + if ((!currentGroups || currentGroups.length < minItems) && minItems > 0) { + const groupsToAdd = minItems - (currentGroups?.length || 0); + const updatedGroups = [...(currentGroups || [])]; + + for (let i = 0; i < groupsToAdd; i++) { + const newGroup = {}; + + // Add fields from configuration + if (props.component.props.fields) { + props.component.props.fields.forEach(field => { + newGroup[field.name] = ''; + }); + } + + updatedGroups.push(newGroup); + } + + const updatedData = { ...formStore.previewFormData, [groupName]: updatedGroups }; + formStore.updatePreviewFormData(updatedData); + } + } +}, { deep: true, immediate: true }); + // Repeating group and dynamic list functionality const addGroupItem = () => { if (props.isPreview) return; @@ -648,6 +712,9 @@ const addGroupItem = () => { // Update the form data const updatedData = { ...formStore.previewFormData, [groupName]: currentGroups }; formStore.updatePreviewFormData(updatedData); + + // Also emit an event to notify parent components about the data change + emit('form-data-updated', updatedData); }; const removeGroupItem = (index) => { @@ -659,12 +726,22 @@ const removeGroupItem = (index) => { // Get current groups const currentGroups = [...(safeGetField(groupName, formStore.previewFormData) || [])]; + // Check if we can remove this item (respect minimum items) + const minItems = props.component.props.minItems || 1; + if (currentGroups.length <= minItems) { + return; + } + // Remove the group at the specified index currentGroups.splice(index, 1); // Update the form data const updatedData = { ...formStore.previewFormData, [groupName]: currentGroups }; formStore.updatePreviewFormData(updatedData); + + // Also emit an event to notify parent components about the data change + // This is important for FormKit integration + emit('form-data-updated', updatedData); }; const addListItem = () => { diff --git a/components/FormBuilderFieldSettingsModal.vue b/components/FormBuilderFieldSettingsModal.vue index cd1f8b2..b6f5fcb 100644 --- a/components/FormBuilderFieldSettingsModal.vue +++ b/components/FormBuilderFieldSettingsModal.vue @@ -939,6 +939,255 @@ if (name && email) { + + + diff --git a/stores/formBuilder.js b/stores/formBuilder.js index b04fd81..12e5ef7 100644 --- a/stores/formBuilder.js +++ b/stores/formBuilder.js @@ -377,6 +377,30 @@ export const useFormBuilderStore = defineStore('formBuilder', { }; this.formComponents.push(newComponent); + + // Initialize preview form data for repeating groups + if (newComponent.type === 'repeating-group' && newComponent.props?.name) { + const groupName = newComponent.props.name; + const minItems = newComponent.props.minItems || 1; + + const initialGroups = []; + for (let i = 0; i < minItems; i++) { + const newGroup = {}; + + // Add fields from configuration + if (newComponent.props.fields) { + newComponent.props.fields.forEach(field => { + newGroup[field.name] = ''; + }); + } + + initialGroups.push(newGroup); + } + + const updatedFormData = { ...this.previewFormData, [groupName]: initialGroups }; + this.updatePreviewFormData(updatedFormData); + } + // Explicitly select the new component this.selectedComponentId = newComponentId; this.hasUnsavedChanges = true; @@ -801,6 +825,33 @@ export const useFormBuilderStore = defineStore('formBuilder', { })); } + // Initialize preview form data with repeating groups + const initialFormData = {}; + this.formComponents.forEach(component => { + if (component.type === 'repeating-group' && component.props?.name) { + const groupName = component.props.name; + const minItems = component.props.minItems || 1; + + const initialGroups = []; + for (let i = 0; i < minItems; i++) { + const newGroup = {}; + + // Add fields from configuration + if (component.props.fields) { + component.props.fields.forEach(field => { + newGroup[field.name] = ''; + }); + } + + initialGroups.push(newGroup); + } + + initialFormData[groupName] = initialGroups; + } + }); + + this.updatePreviewFormData(initialFormData); + // Clear and initialize history when loading a form this.actionHistory = []; this.currentHistoryIndex = -1; @@ -876,6 +927,9 @@ export const useFormBuilderStore = defineStore('formBuilder', { this.actionHistory = []; this.currentHistoryIndex = -1; + // Clear preview form data + this.updatePreviewFormData({}); + // Record the initial empty state this.recordHistory('new_form', { message: 'Created a new empty form'