diff --git a/components/ComponentPreview.vue b/components/ComponentPreview.vue index 92c5e47..34ffb94 100644 --- a/components/ComponentPreview.vue +++ b/components/ComponentPreview.vue @@ -933,6 +933,22 @@ onUnmounted(() => { // Initialize data for components onMounted(() => { + // Initialize default values for standard input fields + if (isInputType.value && props.component.props.name && props.isPreview) { + const fieldName = props.component.props.name; + const currentValue = safeGetField(fieldName, formStore.previewFormData, { warn: false }); + + // If field doesn't have a value yet and has a defaultValue, set it + if ((currentValue === undefined || currentValue === null || currentValue === '') && + props.component.props.defaultValue !== undefined && + props.component.props.defaultValue !== null) { + nextTick(() => { + const updatedData = { ...formStore.previewFormData, [fieldName]: props.component.props.defaultValue }; + formStore.updatePreviewFormData(updatedData); + }); + } + } + // Initialize search and selection data for dynamic lists if (props.component.type === 'dynamic-list') { const listName = props.component.props.name; @@ -983,7 +999,7 @@ onMounted(() => { // If this component has a name, add it to the group if (comp.props && comp.props.name) { - newGroup[comp.props.name] = getDefaultValueForType(comp.type); + newGroup[comp.props.name] = getDefaultValueForType(comp.type, comp); } // Handle layout grid components @@ -1093,7 +1109,7 @@ watch(() => props.component.props.minItems, (newMinItems, oldMinItems) => { // If this component has a name, add it to the group if (comp.props && comp.props.name) { - newGroup[comp.props.name] = getDefaultValueForType(comp.type); + newGroup[comp.props.name] = getDefaultValueForType(comp.type, comp); } // Handle layout grid components @@ -1592,12 +1608,17 @@ const getFieldValue = (component) => { } } + // Check for defaultValue property first + if (component.props.defaultValue !== undefined && component.props.defaultValue !== null) { + return component.props.defaultValue; + } + // For select fields, return first option value as default if no form data exists if (component.type === 'select' && component.props.options && component.props.options.length > 0) { return component.props.options[0].value || ''; } - // Return component default value if no form data exists + // Return component value property if no default value exists return component.props.value || ''; }; @@ -1659,6 +1680,11 @@ const getRepeatingGroupFieldValue = (group, fieldName, fieldType, component = nu // Helper function to get default values based on field type const getDefaultValueForType = (fieldType, component = null) => { + // First check if component has a defaultValue property + if (component && component.props && component.props.defaultValue !== undefined) { + return component.props.defaultValue; + } + switch (fieldType) { case 'number': return 0; @@ -1687,12 +1713,8 @@ const addRepeatingGroupItem = (groupName, children) => { // If this component has a name, add it to the item if (comp.props && comp.props.name) { - // Use the same default value logic as getDefaultValueForType - if (comp.type === 'select' && comp.props.options && comp.props.options.length > 0) { - newItem[comp.props.name] = comp.props.options[0].value || ''; - } else { - newItem[comp.props.name] = getDefaultValueForType(comp.type); - } + // Use the getDefaultValueForType function with the component + newItem[comp.props.name] = getDefaultValueForType(comp.type, comp); } // Handle layout grid components diff --git a/components/FormBuilderFieldSettingsModal.vue b/components/FormBuilderFieldSettingsModal.vue index f3d5210..a481075 100644 --- a/components/FormBuilderFieldSettingsModal.vue +++ b/components/FormBuilderFieldSettingsModal.vue @@ -280,6 +280,20 @@ rows="2" /> + + + { return ['text', 'textarea', 'email', 'password', 'url', 'tel'].includes(props.component?.type) }) +// Default Value Field Helpers +const showDefaultValueField = () => { + if (!props.component) return false + + // List of components that support default values + const supportedTypes = [ + 'text', 'textarea', 'number', 'email', 'password', 'url', 'tel', + 'mask', 'select', 'searchSelect', 'checkbox', 'radio', 'switch', + 'date', 'time', 'datetime-local', 'range', 'color', 'hidden' + ] + + return supportedTypes.includes(props.component.type) +} + +const getDefaultValueFieldType = () => { + if (!props.component) return 'text' + + const fieldTypeMap = { + 'text': 'text', + 'textarea': 'textarea', + 'number': 'number', + 'email': 'email', + 'password': 'text', + 'url': 'url', + 'tel': 'tel', + 'mask': 'text', + 'select': 'select', + 'searchSelect': 'select', + 'checkbox': 'checkbox', + 'radio': 'select', + 'switch': 'switch', + 'date': 'date', + 'time': 'time', + 'datetime-local': 'datetime-local', + 'range': 'number', + 'color': 'color', + 'hidden': 'text' + } + + return fieldTypeMap[props.component.type] || 'text' +} + +const getDefaultValueHelp = () => { + if (!props.component) return 'Initial value when the form loads' + + const helpTexts = { + 'select': 'Choose the default selected option', + 'searchSelect': 'Choose the default selected option', + 'checkbox': 'Select the default checked options', + 'radio': 'Choose the default selected option', + 'switch': 'Set the default on/off state', + 'date': 'Set the default date (YYYY-MM-DD)', + 'time': 'Set the default time (HH:MM)', + 'datetime-local': 'Set the default date and time', + 'range': 'Set the default slider value', + 'color': 'Choose the default color', + 'number': 'Set the default numeric value' + } + + return helpTexts[props.component.type] || 'Initial value when the form loads' +} + +const getDefaultValuePlaceholder = () => { + if (!props.component) return '' + + const placeholders = { + 'text': 'e.g., John Doe', + 'email': 'e.g., user@example.com', + 'url': 'e.g., https://example.com', + 'tel': 'e.g., +1234567890', + 'number': 'e.g., 100', + 'date': 'YYYY-MM-DD', + 'time': 'HH:MM', + 'datetime-local': 'YYYY-MM-DDTHH:MM' + } + + return placeholders[props.component.type] || '' +} + // Safe HTML preview for custom HTML component const getSafeHtmlPreview = (htmlContent) => { if (!htmlContent) return ''