Enhance Default Value Handling in Form Builder Components

- Updated ComponentPreview.vue to initialize default values for standard input fields based on the component's defaultValue property, improving user experience during form previews.
- Enhanced FormBuilderFieldSettingsModal.vue by introducing a Default Value field, allowing users to set initial values for various input types, with appropriate help texts and placeholders for better guidance.
- Implemented helper functions to determine the visibility and type of the Default Value field based on the component type, ensuring consistent behavior across supported input types.
This commit is contained in:
Afiq 2025-08-08 12:24:42 +08:00
parent 2b322c38c6
commit b72bf2f89c
2 changed files with 124 additions and 9 deletions

View File

@ -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

View File

@ -280,6 +280,20 @@
rows="2"
/>
<!-- Default Value Field -->
<FormKit
v-if="showDefaultValueField()"
:type="getDefaultValueFieldType()"
label="Default Value"
name="defaultValue"
v-model="configModel.defaultValue"
:help="getDefaultValueHelp()"
:classes="{ outer: 'field-wrapper' }"
:placeholder="getDefaultValuePlaceholder()"
:options="component.type === 'select' || component.type === 'radio' || component.type === 'checkbox' ? configModel.options : undefined"
:rows="component.type === 'textarea' ? 2 : undefined"
/>
<FormKit
v-if="showField('rows')"
type="number"
@ -3329,6 +3343,85 @@ const isTextBasedField = computed(() => {
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 ''