Update Form Builder Documentation and Technical Appendix
- Enhanced the Form Builder documentation with a comprehensive overview, getting started guide, and detailed descriptions of available components and their configurations. - Updated the Technical Appendix to include architecture overview, technology stack, project structure, and component architecture. - Improved clarity on state management, validation system, and event handling within the Form Builder. - Added best practices for form design and user experience considerations. - Last updated date included for both documentation files.
This commit is contained in:
parent
55fb5a9c54
commit
3b4b6437bc
@ -2,166 +2,208 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The Form Builder is a drag-and-drop interface for creating dynamic forms. It allows users to build forms by selecting input components, configuring them, and arranging them in the desired order. The form builder follows the design pattern of the code playground with a full-screen empty layout.
|
The Form Builder is a powerful drag-and-drop interface for creating dynamic forms. It provides an intuitive, visual way to build forms by selecting components, configuring their properties, and arranging them in your desired layout. Perfect for creating everything from simple contact forms to complex multi-step surveys.
|
||||||
|
|
||||||
## Files Structure
|
> For technical implementation details, please refer to [Form Builder Technical Appendix](FORM_BUILDER_TECHNICAL_APPENDIX.md)
|
||||||
|
|
||||||
### Pages
|
## Getting Started
|
||||||
|
|
||||||
1. **`pages/form-builder/index.vue`**
|
### Accessing the Form Builder
|
||||||
- Main form builder interface with three-panel layout
|
1. Navigate to `/form-builder` in your browser
|
||||||
- Drag and drop interface for building forms
|
2. You'll see a three-panel interface:
|
||||||
- Uses empty layout for fullscreen experience
|
- Left: Component Library
|
||||||
- Contains form name input and save/preview actions
|
- Middle: Form Canvas
|
||||||
- [View File](pages/form-builder/index.vue)
|
- Right: Configuration Panel
|
||||||
|
|
||||||
2. **`pages/form-builder/manage.vue`**
|
### Quick Start Guide
|
||||||
- Form management interface
|
1. **Create a New Form**
|
||||||
- Lists saved forms with search functionality
|
- Click "New Form" in the header
|
||||||
- Provides edit and delete actions for each form
|
- Enter a form name and description
|
||||||
- Uses empty layout and matches design of main page
|
- Start adding components
|
||||||
- [View File](pages/form-builder/manage.vue)
|
|
||||||
|
|
||||||
### Components
|
2. **Add Components**
|
||||||
|
- Drag components from the left panel
|
||||||
|
- Or click components to add them to the end
|
||||||
|
- Components are organized by category for easy finding
|
||||||
|
|
||||||
3. **`components/FormBuilderComponents.vue`**
|
3. **Configure Components**
|
||||||
- Left panel component that displays available form elements
|
- Click any component in the canvas to select it
|
||||||
- Categorizes components into groups (Basic Inputs, Selection Inputs, etc.)
|
- Use the right panel to configure its properties
|
||||||
- Provides search functionality for finding components
|
- Changes are previewed in real-time
|
||||||
- Components can be dragged to the canvas
|
|
||||||
- Uses Material Design icons
|
|
||||||
- [View File](components/FormBuilderComponents.vue)
|
|
||||||
|
|
||||||
4. **`components/FormBuilderCanvas.vue`**
|
4. **Save and Preview**
|
||||||
- Middle panel component that displays the form being built
|
- Click "Save" to store your form
|
||||||
- Handles drag-and-drop reordering of components
|
- Use "Preview" to test the form
|
||||||
- Renders form elements with preview mode
|
- Access saved forms via "Manage Forms"
|
||||||
- Provides selection, deletion, and reordering capabilities
|
|
||||||
- Uses vuedraggable for drag-and-drop functionality
|
|
||||||
- [View File](components/FormBuilderCanvas.vue)
|
|
||||||
|
|
||||||
5. **`components/FormBuilderConfiguration.vue`**
|
## Available Components
|
||||||
- Right panel component for configuring selected form elements
|
|
||||||
- Tabbed interface with Basic, Validation, and Advanced sections
|
|
||||||
- Dynamically shows/hides fields based on component type
|
|
||||||
- Provides rich validation options
|
|
||||||
- [View File](components/FormBuilderConfiguration.vue)
|
|
||||||
|
|
||||||
6. **`components/ComponentPreview.vue`**
|
### Basic Inputs
|
||||||
- Renders a preview of form components
|
Perfect for collecting simple text and numeric data:
|
||||||
- Handles different component types (inputs, headings, paragraphs, etc.)
|
- **Text Field**: Single line text input
|
||||||
- Uses FormKit for rendering form inputs
|
- Use for: Names, titles, short answers
|
||||||
- Provides formatting for non-input elements (headings, paragraphs, dividers)
|
- Features: Placeholder text, help text, validation
|
||||||
- [View File](components/ComponentPreview.vue)
|
|
||||||
|
|
||||||
### State Management
|
- **Text Area**: Multi-line text input
|
||||||
|
- Use for: Comments, descriptions, long answers
|
||||||
|
- Features: Resizable, character count option
|
||||||
|
|
||||||
7. **`stores/formBuilder.js`**
|
- **Number**: Numeric input field
|
||||||
- Pinia store for managing form builder state
|
- Use for: Age, quantity, numeric values
|
||||||
- Handles form components, selected component, dragging state
|
- Features: Min/max limits, step values
|
||||||
- Provides actions for adding, updating, moving, and deleting components
|
|
||||||
- Handles form saving and loading with localStorage
|
|
||||||
- Persists saved forms
|
|
||||||
- [View File](stores/formBuilder.js)
|
|
||||||
|
|
||||||
### Utilities
|
- **Email**: Email address input
|
||||||
|
- Use for: Contact forms, user registration
|
||||||
|
- Features: Built-in email validation
|
||||||
|
|
||||||
8. **`composables/useToast.js`**
|
- **Password**: Secure password input
|
||||||
- Toast notification composable for consistent toast messages
|
- Use for: Login forms, security inputs
|
||||||
- Wraps Vue Toastification with standardized configurations
|
- Features: Password masking, strength indicators
|
||||||
- Provides success, error, warning, and info methods
|
|
||||||
- [View File](composables/useToast.js)
|
|
||||||
|
|
||||||
## Key Features
|
### Selection Inputs
|
||||||
|
For choosing from predefined options:
|
||||||
|
- **Select Dropdown**: Single selection menu
|
||||||
|
- Use for: Country selection, categories
|
||||||
|
- Features: Search, option groups, custom values
|
||||||
|
|
||||||
### Form Building
|
- **Checkbox Group**: Multiple choice selection
|
||||||
- Drag-and-drop interface for adding components to the form
|
- Use for: Multiple selections, preferences
|
||||||
- Reordering components via drag-and-drop
|
- Features: Select all, option layout control
|
||||||
- Configuring component properties (labels, placeholders, validation, etc.)
|
|
||||||
- Real-time preview of the form being built
|
|
||||||
|
|
||||||
### Component Types
|
- **Radio Group**: Single choice selection
|
||||||
- **Basic Inputs**: Text, Textarea, Number, Email, Password
|
- Use for: Exclusive choices, yes/no questions
|
||||||
- **Selection Inputs**: Select, Checkbox, Radio
|
- Features: Button or traditional style
|
||||||
- **Date and Time**: Date Picker, Time Picker, Date & Time
|
|
||||||
- **Advanced**: File Upload, Repeater, Group
|
|
||||||
- **Layout**: Heading, Paragraph, Divider
|
|
||||||
|
|
||||||
### Form Management
|
### Date and Time
|
||||||
- Save forms to localStorage
|
Temporal input components:
|
||||||
- List all saved forms
|
- **Date Picker**: Date selection
|
||||||
- Search for forms by name
|
- Use for: Birthdays, scheduling
|
||||||
- Edit existing forms
|
- Features: Date range limits, format options
|
||||||
- Delete forms
|
|
||||||
|
- **Time Picker**: Time selection
|
||||||
|
- Use for: Scheduling, time slots
|
||||||
|
- Features: 12/24 hour format, minute steps
|
||||||
|
|
||||||
|
- **Date & Time**: Combined selection
|
||||||
|
- Use for: Event scheduling, appointments
|
||||||
|
- Features: Single field for date and time
|
||||||
|
|
||||||
|
### Advanced Components
|
||||||
|
Specialized input types:
|
||||||
|
- **File Upload**: File input field
|
||||||
|
- Use for: Document upload, image submission
|
||||||
|
- Features: File type restrictions, size limits
|
||||||
|
|
||||||
|
- **Repeater**: Repeatable field groups
|
||||||
|
- Use for: Multiple entries, dynamic lists
|
||||||
|
- Features: Add/remove controls, ordering
|
||||||
|
|
||||||
|
- **Group**: Field organization
|
||||||
|
- Use for: Related fields, form sections
|
||||||
|
- Features: Collapsible, conditional display
|
||||||
|
|
||||||
|
### Layout Components
|
||||||
|
Form structure and organization:
|
||||||
|
- **Heading**: Section titles
|
||||||
|
- Use for: Form sections, categories
|
||||||
|
- Features: Multiple heading levels
|
||||||
|
|
||||||
|
- **Paragraph**: Descriptive text
|
||||||
|
- Use for: Instructions, help text
|
||||||
|
- Features: Rich text formatting
|
||||||
|
|
||||||
|
- **Divider**: Visual separator
|
||||||
|
- Use for: Section breaks
|
||||||
|
- Features: Various styles
|
||||||
|
|
||||||
|
## Form Configuration
|
||||||
|
|
||||||
|
### Basic Settings
|
||||||
|
- Form name and description
|
||||||
|
- Success/error messages
|
||||||
|
- Submit button text
|
||||||
|
- Form layout options
|
||||||
|
|
||||||
|
### Validation Options
|
||||||
|
- Required fields
|
||||||
|
- Input patterns
|
||||||
|
- Custom error messages
|
||||||
|
- Cross-field validation
|
||||||
|
|
||||||
|
### Advanced Settings
|
||||||
|
- Form submission behavior
|
||||||
|
- Success/failure redirects
|
||||||
|
- Custom CSS classes
|
||||||
|
- Event handlers
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Form Design
|
||||||
|
1. Group related fields together
|
||||||
|
2. Use clear, concise labels
|
||||||
|
3. Provide help text for complex fields
|
||||||
|
4. Maintain consistent styling
|
||||||
|
5. Consider mobile users
|
||||||
|
|
||||||
### Validation
|
### Validation
|
||||||
- Built-in validation options (required, email, min, max, etc.)
|
1. Validate on the appropriate event
|
||||||
- Quick validation buttons
|
2. Provide clear error messages
|
||||||
- Validation rule syntax help
|
3. Show validation status clearly
|
||||||
- Required field checkbox
|
4. Use appropriate validation rules
|
||||||
|
|
||||||
## UI/UX Design
|
### User Experience
|
||||||
|
1. Keep forms as short as possible
|
||||||
|
2. Use appropriate field types
|
||||||
|
3. Provide clear instructions
|
||||||
|
4. Show progress in multi-step forms
|
||||||
|
5. Ensure keyboard navigation
|
||||||
|
|
||||||
- Professional dark header with logo and main actions
|
## Managing Forms
|
||||||
- Three-panel layout for Components, Canvas, and Configuration
|
|
||||||
- Material Design icons throughout
|
|
||||||
- Empty layout for fullscreen experience
|
|
||||||
- Responsive design that works on mobile and desktop
|
|
||||||
- Consistent styling with the Code Playground
|
|
||||||
|
|
||||||
## Implementation Details
|
### Saved Forms
|
||||||
|
- View all forms in the management interface
|
||||||
|
- Search and filter forms
|
||||||
|
- Duplicate existing forms
|
||||||
|
- Archive unused forms
|
||||||
|
|
||||||
### Layout Structure
|
### Form Actions
|
||||||
- Header with navigation and primary actions
|
- Preview: Test the form
|
||||||
- Form name input section
|
- Edit: Modify form structure
|
||||||
- Three-panel main content area
|
- Delete: Remove unused forms
|
||||||
- Preview modal for testing the form
|
- Export: Save form configuration
|
||||||
|
|
||||||
### State Management
|
### Form Analytics
|
||||||
- Centralized Pinia store for form state
|
- View submission statistics
|
||||||
- Computed properties for derived state
|
- Track completion rates
|
||||||
- Watchers for reactivity
|
- Identify problem fields
|
||||||
- Local storage for persistence
|
- Monitor usage patterns
|
||||||
|
|
||||||
### Component Communication
|
## Troubleshooting
|
||||||
- Props for parent-to-child data flow
|
|
||||||
- Events for child-to-parent communication
|
|
||||||
- Store actions for cross-component communication
|
|
||||||
|
|
||||||
### Styling
|
### Common Issues
|
||||||
- Tailwind CSS for utility-first styling
|
1. **Form Not Saving**
|
||||||
- Custom transitions and animations
|
- Check your connection
|
||||||
- Responsive breakpoints
|
- Ensure form has a name
|
||||||
- Consistent color scheme
|
- Verify all components are valid
|
||||||
|
|
||||||
## Usage Instructions
|
2. **Components Not Dragging**
|
||||||
|
- Clear browser cache
|
||||||
|
- Check for JavaScript errors
|
||||||
|
- Ensure proper mouse/touch interaction
|
||||||
|
|
||||||
1. Navigate to `/form-builder` to access the form builder
|
3. **Validation Not Working**
|
||||||
2. Add components by dragging them from the left panel to the canvas
|
- Verify validation rules syntax
|
||||||
3. Select a component on the canvas to configure it in the right panel
|
- Check field names are unique
|
||||||
4. Save the form using the Save button in the header
|
- Ensure validation is enabled
|
||||||
5. Preview the form by clicking the Preview button
|
|
||||||
6. Manage saved forms by clicking the Manage Forms button
|
|
||||||
7. Search, edit, or delete forms in the management interface
|
|
||||||
|
|
||||||
## Development Notes
|
### Getting Help
|
||||||
|
- Check the technical documentation
|
||||||
- The form builder uses vuedraggable for drag-and-drop functionality
|
- Contact support team
|
||||||
- FormKit is used for all form inputs
|
- Submit bug reports
|
||||||
- Material Design icons are used throughout
|
- Request features
|
||||||
- The form builder follows the design patterns established in the code playground
|
|
||||||
- All components are responsive and work on mobile devices
|
|
||||||
|
|
||||||
## Future Enhancements
|
|
||||||
|
|
||||||
- Backend integration for saving forms to a database
|
|
||||||
- Form publishing and sharing functionality
|
|
||||||
- Form versioning
|
|
||||||
- Form templates
|
|
||||||
- More advanced validation options
|
|
||||||
- Conditional display of form fields
|
|
||||||
- Multi-page forms
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This documentation was generated on April 9, 2025.
|
For technical details about implementation, component structure, and development guidelines, please refer to the [Technical Appendix](FORM_BUILDER_TECHNICAL_APPENDIX.md).
|
||||||
|
|
||||||
|
Last updated: April 9, 2025
|
@ -1,46 +1,140 @@
|
|||||||
# Form Builder Technical Appendix
|
# Form Builder Technical Appendix
|
||||||
|
|
||||||
This document provides technical details and code snippets for the form builder implementation.
|
This document provides technical implementation details for developers working with the Form Builder system.
|
||||||
|
|
||||||
## Table of Contents
|
> For user documentation and usage guidelines, please refer to [Form Builder Documentation](FORM_BUILDER_DOCUMENTATION.md)
|
||||||
|
|
||||||
1. [Component Structure](#component-structure)
|
## Architecture Overview
|
||||||
2. [State Management](#state-management)
|
|
||||||
3. [Drag and Drop Implementation](#drag-and-drop-implementation)
|
|
||||||
4. [FormKit Integration](#formkit-integration)
|
|
||||||
5. [Validation System](#validation-system)
|
|
||||||
6. [Icons and UI Elements](#icons-and-ui-elements)
|
|
||||||
7. [Responsive Design](#responsive-design)
|
|
||||||
|
|
||||||
## Component Structure
|
### Technology Stack
|
||||||
|
- **Frontend Framework**: Nuxt 3 / Vue 3
|
||||||
|
- **State Management**: Pinia
|
||||||
|
- **Form Library**: FormKit
|
||||||
|
- **UI Framework**: Tailwind CSS
|
||||||
|
- **Icons**: Material Design Icons
|
||||||
|
- **Drag & Drop**: vuedraggable
|
||||||
|
|
||||||
The form builder is built with a modular component structure:
|
### Key Dependencies
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"@formkit/nuxt": "^1.0.0",
|
||||||
|
"@pinia/nuxt": "^0.4.11",
|
||||||
|
"vuedraggable": "^4.1.0",
|
||||||
|
"@vueuse/core": "^10.1.2",
|
||||||
|
"tailwindcss": "^3.3.2"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
pages/
|
pages/
|
||||||
├── form-builder/
|
├── form-builder/
|
||||||
│ ├── index.vue # Main form builder page
|
│ ├── index.vue # Main builder interface
|
||||||
│ └── manage.vue # Form management page
|
│ └── manage.vue # Form management
|
||||||
components/
|
components/
|
||||||
├── FormBuilderComponents.vue # Left panel components
|
├── FormBuilderComponents.vue # Component library
|
||||||
├── FormBuilderCanvas.vue # Middle panel canvas
|
├── FormBuilderCanvas.vue # Form canvas
|
||||||
├── FormBuilderConfiguration.vue # Right panel configuration
|
├── FormBuilderConfiguration.vue # Component config
|
||||||
└── ComponentPreview.vue # Component rendering
|
└── ComponentPreview.vue # Preview renderer
|
||||||
stores/
|
stores/
|
||||||
└── formBuilder.js # State management
|
└── formBuilder.js # State management
|
||||||
composables/
|
composables/
|
||||||
└── useToast.js # Toast notifications
|
└── useToast.js # Toast notifications
|
||||||
|
types/
|
||||||
|
└── form-builder.d.ts # TypeScript definitions
|
||||||
|
```
|
||||||
|
|
||||||
|
## Component Architecture
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
|
||||||
|
1. **FormBuilderComponents.vue**
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
const emit = defineEmits(['add-component']);
|
||||||
|
const searchQuery = ref('');
|
||||||
|
|
||||||
|
// Component categories and definitions
|
||||||
|
const availableComponents = [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
name: 'Text Field',
|
||||||
|
category: 'Basic Inputs',
|
||||||
|
icon: 'material-symbols:text-fields',
|
||||||
|
defaultProps: {
|
||||||
|
type: 'text',
|
||||||
|
placeholder: '',
|
||||||
|
validation: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// ... other components
|
||||||
|
];
|
||||||
|
|
||||||
|
// Search and filtering logic
|
||||||
|
const filteredComponents = computed(() => {
|
||||||
|
if (!searchQuery.value) return availableComponents;
|
||||||
|
return availableComponents.filter(component =>
|
||||||
|
component.name.toLowerCase().includes(searchQuery.value.toLowerCase())
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Drag handlers
|
||||||
|
const onDragStart = (event, component) => {
|
||||||
|
event.dataTransfer.effectAllowed = 'copy';
|
||||||
|
event.dataTransfer.setData('component', JSON.stringify(component));
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **FormBuilderCanvas.vue**
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
components: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Drag and drop configuration
|
||||||
|
const dragOptions = {
|
||||||
|
animation: 300,
|
||||||
|
group: 'form-components',
|
||||||
|
ghostClass: 'ghost',
|
||||||
|
handle: '.drag-handle'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Component selection
|
||||||
|
const selectComponent = (id) => {
|
||||||
|
formStore.selectComponent(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Grid system implementation
|
||||||
|
const calculateGridPosition = (index) => {
|
||||||
|
return {
|
||||||
|
gridColumn: `span ${component.width || 12} / span ${component.width || 12}`,
|
||||||
|
order: index
|
||||||
|
};
|
||||||
|
};
|
||||||
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
## State Management
|
## State Management
|
||||||
|
|
||||||
### Pinia Store (stores/formBuilder.js)
|
### Pinia Store Structure
|
||||||
|
```typescript
|
||||||
|
interface FormState {
|
||||||
|
formComponents: FormComponent[];
|
||||||
|
selectedComponentId: string | null;
|
||||||
|
formName: string;
|
||||||
|
formDescription: string;
|
||||||
|
isDraggingOver: boolean;
|
||||||
|
savedForms: SavedForm[];
|
||||||
|
}
|
||||||
|
|
||||||
The form builder uses Pinia for state management:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
export const useFormBuilderStore = defineStore('formBuilder', {
|
export const useFormBuilderStore = defineStore('formBuilder', {
|
||||||
state: () => ({
|
state: (): FormState => ({
|
||||||
formComponents: [],
|
formComponents: [],
|
||||||
selectedComponentId: null,
|
selectedComponentId: null,
|
||||||
formName: 'New Form',
|
formName: 'New Form',
|
||||||
@ -50,297 +144,215 @@ export const useFormBuilderStore = defineStore('formBuilder', {
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
selectedComponent: (state) => {
|
selectedComponent: (state) => // Implementation
|
||||||
return state.selectedComponentId
|
formConfig: (state) => // Implementation
|
||||||
? state.formComponents.find(c => c.id === state.selectedComponentId)
|
|
||||||
: null;
|
|
||||||
},
|
|
||||||
|
|
||||||
formConfig: (state) => {
|
|
||||||
return {
|
|
||||||
id: uuidv4(),
|
|
||||||
name: state.formName,
|
|
||||||
description: state.formDescription,
|
|
||||||
components: state.formComponents.map(c => ({
|
|
||||||
type: c.type,
|
|
||||||
props: c.props
|
|
||||||
})),
|
|
||||||
createdAt: new Date().toISOString()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
addComponent(component) {
|
addComponent(component: FormComponent) // Implementation
|
||||||
const newComponent = {
|
updateComponent(id: string, updates: Partial<FormComponent>) // Implementation
|
||||||
...component,
|
deleteComponent(id: string) // Implementation
|
||||||
id: uuidv4(),
|
moveComponent(oldIndex: number, newIndex: number) // Implementation
|
||||||
props: {
|
|
||||||
...component.defaultProps,
|
|
||||||
name: `${component.type}_${this.formComponents.length + 1}`,
|
|
||||||
label: `${component.name} ${this.formComponents.length + 1}`
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.formComponents.push(newComponent);
|
|
||||||
this.selectComponent(newComponent.id);
|
|
||||||
},
|
|
||||||
|
|
||||||
// ... other actions
|
|
||||||
},
|
|
||||||
|
|
||||||
persist: {
|
|
||||||
paths: ['savedForms']
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## Drag and Drop Implementation
|
## Form Component Types
|
||||||
|
|
||||||
### Draggable Components
|
### Type Definitions
|
||||||
|
```typescript
|
||||||
|
interface BaseComponent {
|
||||||
|
id: string;
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
category: ComponentCategory;
|
||||||
|
icon: string;
|
||||||
|
props: BaseComponentProps;
|
||||||
|
}
|
||||||
|
|
||||||
The form builder uses `vuedraggable` for drag-and-drop functionality:
|
interface BaseComponentProps {
|
||||||
|
name: string;
|
||||||
|
label: string;
|
||||||
|
help?: string;
|
||||||
|
validation?: string;
|
||||||
|
width?: number;
|
||||||
|
}
|
||||||
|
|
||||||
```vue
|
interface InputComponent extends BaseComponent {
|
||||||
<!-- FormBuilderCanvas.vue -->
|
props: InputComponentProps;
|
||||||
<draggable
|
}
|
||||||
v-model="componentList"
|
|
||||||
group="form-components"
|
|
||||||
item-key="id"
|
|
||||||
handle=".drag-handle"
|
|
||||||
ghost-class="ghost"
|
|
||||||
animation="300"
|
|
||||||
@end="onDragEnd"
|
|
||||||
>
|
|
||||||
<template #item="{ element, index }">
|
|
||||||
<div class="form-component relative mb-4 border rounded-md overflow-hidden">
|
|
||||||
<!-- Component content -->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</draggable>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Drag Start Handler
|
interface SelectComponent extends BaseComponent {
|
||||||
|
props: SelectComponentProps;
|
||||||
|
}
|
||||||
|
|
||||||
```javascript
|
// Additional type definitions...
|
||||||
// FormBuilderComponents.vue
|
|
||||||
const onDragStart = (event, component) => {
|
|
||||||
event.dataTransfer.effectAllowed = 'copy';
|
|
||||||
event.dataTransfer.setData('component', JSON.stringify(component));
|
|
||||||
emit('add-component', component);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Drop Handler
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// pages/form-builder/index.vue
|
|
||||||
const handleDrop = (event) => {
|
|
||||||
formStore.setDraggingOver(false);
|
|
||||||
const componentData = JSON.parse(event.dataTransfer.getData('component'));
|
|
||||||
formStore.addComponent(componentData);
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
## FormKit Integration
|
|
||||||
|
|
||||||
### Component Preview
|
|
||||||
|
|
||||||
The form builder uses FormKit to render form components:
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<!-- ComponentPreview.vue -->
|
|
||||||
<FormKit
|
|
||||||
v-if="isInputType"
|
|
||||||
:id="`preview-${component.id}`"
|
|
||||||
:type="component.props.type"
|
|
||||||
:name="component.props.name"
|
|
||||||
:label="component.props.label"
|
|
||||||
:help="component.props.help"
|
|
||||||
:placeholder="component.props.placeholder"
|
|
||||||
:validation="component.props.validation"
|
|
||||||
:validation-visibility="isPreview ? 'live' : 'blur'"
|
|
||||||
:disabled="isPreview"
|
|
||||||
:options="component.props.options || undefined"
|
|
||||||
:value="component.props.value || undefined"
|
|
||||||
:accept="component.props.accept || undefined"
|
|
||||||
:max="component.props.max || undefined"
|
|
||||||
/>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Validation System
|
## Validation System
|
||||||
|
|
||||||
### Validation Configuration
|
### Implementation
|
||||||
|
```typescript
|
||||||
|
const validationRules = {
|
||||||
|
required: 'Value is required',
|
||||||
|
email: 'Invalid email format',
|
||||||
|
min: (min: number) => `Minimum value is ${min}`,
|
||||||
|
max: (max: number) => `Maximum value is ${max}`,
|
||||||
|
between: (min: number, max: number) =>
|
||||||
|
`Value must be between ${min} and ${max}`,
|
||||||
|
pattern: (pattern: string) =>
|
||||||
|
`Value must match pattern: ${pattern}`
|
||||||
|
};
|
||||||
|
|
||||||
The configuration panel provides validation options:
|
const validateField = (value: any, rules: string) => {
|
||||||
|
// Validation implementation
|
||||||
```vue
|
};
|
||||||
<!-- FormBuilderConfiguration.vue -->
|
|
||||||
<RsTabItem title="Validation">
|
|
||||||
<div class="space-y-4 pt-2">
|
|
||||||
<div class="mb-4">
|
|
||||||
<h4 class="text-sm font-medium mb-2">Available Validations</h4>
|
|
||||||
<div class="grid grid-cols-2 gap-2">
|
|
||||||
<RsButton
|
|
||||||
v-for="validator in availableValidators"
|
|
||||||
:key="validator.name"
|
|
||||||
size="sm"
|
|
||||||
variant="tertiary"
|
|
||||||
class="text-left justify-start"
|
|
||||||
@click="addValidator(validator.name)"
|
|
||||||
>
|
|
||||||
{{ validator.label }}
|
|
||||||
</RsButton>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<FormKit
|
|
||||||
type="textarea"
|
|
||||||
label="Validation Rules"
|
|
||||||
name="validation"
|
|
||||||
v-model="configModel.validation"
|
|
||||||
help="Comma-separated validation rules (e.g., required,email,length:5,15)"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Validation help -->
|
|
||||||
</div>
|
|
||||||
</RsTabItem>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Available Validators
|
## Grid System
|
||||||
|
|
||||||
```javascript
|
### Implementation
|
||||||
const availableValidators = [
|
```typescript
|
||||||
{ name: 'required', label: 'Required' },
|
const gridSystem = {
|
||||||
{ name: 'email', label: 'Email' },
|
columns: 12,
|
||||||
{ name: 'url', label: 'URL' },
|
breakpoints: {
|
||||||
{ name: 'number', label: 'Number' },
|
sm: 640,
|
||||||
{ name: 'min:5', label: 'Min Length/Value' },
|
md: 768,
|
||||||
{ name: 'max:100', label: 'Max Length/Value' },
|
lg: 1024,
|
||||||
{ name: 'between:5,10', label: 'Between Range' },
|
xl: 1280
|
||||||
{ name: 'date', label: 'Date' },
|
|
||||||
{ name: 'matches:/pattern/', label: 'Pattern Match' }
|
|
||||||
];
|
|
||||||
```
|
|
||||||
|
|
||||||
## Icons and UI Elements
|
|
||||||
|
|
||||||
### Material Design Icons
|
|
||||||
|
|
||||||
The form builder uses Material Design icons:
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<Icon name="material-symbols:layers-outline" class="w-16 h-16 mb-4" />
|
|
||||||
```
|
|
||||||
|
|
||||||
### Component Icons
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// FormBuilderComponents.vue
|
|
||||||
const availableComponents = [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
name: 'Text Field',
|
|
||||||
category: 'Basic Inputs',
|
|
||||||
icon: 'material-symbols:text-fields',
|
|
||||||
// ...
|
|
||||||
},
|
},
|
||||||
// ...
|
calculateSpan: (width: number) =>
|
||||||
];
|
Math.min(Math.max(1, Math.round(width * 12)), 12)
|
||||||
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
## Responsive Design
|
## Event Handling
|
||||||
|
|
||||||
### Responsive Layout
|
### Component Events
|
||||||
|
```typescript
|
||||||
The form builder uses a responsive layout that adapts to different screen sizes:
|
const componentEvents = {
|
||||||
|
onAdd: (event: DragEvent) => void;
|
||||||
```vue
|
onUpdate: (event: UpdateEvent) => void;
|
||||||
<!-- pages/form-builder/index.vue -->
|
onSelect: (id: string) => void;
|
||||||
<div class="flex-1 flex flex-col lg:flex-row overflow-hidden">
|
onDelete: (id: string) => void;
|
||||||
<!-- Left Panel -->
|
onDuplicate: (id: string) => void;
|
||||||
<div class="lg:w-1/4 border-r border-gray-200 bg-white overflow-hidden flex flex-col">
|
onValidate: (component: FormComponent) => ValidationResult;
|
||||||
<!-- Left panel content -->
|
};
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Middle Panel -->
|
|
||||||
<div class="lg:w-2/4 bg-white overflow-hidden flex flex-col border-t lg:border-t-0 lg:border-r border-gray-200">
|
|
||||||
<!-- Middle panel content -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Right Panel -->
|
|
||||||
<div class="lg:w-1/4 bg-white overflow-hidden flex flex-col border-t lg:border-t-0">
|
|
||||||
<!-- Right panel content -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Responsive Header
|
## Performance Optimization
|
||||||
|
|
||||||
```vue
|
### Implementation Details
|
||||||
<header class="bg-gray-800 p-2 flex flex-wrap items-center justify-between text-white">
|
1. **Component Lazy Loading**
|
||||||
<div class="flex items-center mb-2 sm:mb-0 gap-4">
|
```typescript
|
||||||
<!-- Logo and back button -->
|
const ComponentPreview = defineAsyncComponent(() =>
|
||||||
</div>
|
import('./ComponentPreview.vue')
|
||||||
<div class="flex flex-wrap items-center space-x-2">
|
);
|
||||||
<!-- Actions -->
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Component Data Structure
|
2. **Virtual Scrolling**
|
||||||
|
```typescript
|
||||||
|
const virtualScroller = {
|
||||||
|
itemSize: 50,
|
||||||
|
minItemsPerPage: 10,
|
||||||
|
maxBufferPx: 200
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### Form Component Structure
|
3. **Debounced Updates**
|
||||||
|
```typescript
|
||||||
|
const debouncedSave = useDebounceFn(() => {
|
||||||
|
saveFormToStorage();
|
||||||
|
}, 500);
|
||||||
|
```
|
||||||
|
|
||||||
```javascript
|
## Development Guidelines
|
||||||
// Example of a form component object
|
|
||||||
{
|
### Component Development
|
||||||
id: "550e8400-e29b-41d4-a716-446655440000", // UUID
|
1. Follow Vue 3 Composition API patterns
|
||||||
type: "text",
|
2. Implement proper TypeScript types
|
||||||
name: "Text Field",
|
3. Use props validation
|
||||||
category: "Basic Inputs",
|
4. Emit typed events
|
||||||
icon: "material-symbols:text-fields",
|
5. Document component API
|
||||||
props: {
|
|
||||||
type: "text",
|
### State Management
|
||||||
name: "text_1",
|
1. Use Pinia for global state
|
||||||
label: "Text Field 1",
|
2. Implement proper actions and getters
|
||||||
placeholder: "Enter text...",
|
3. Use computed properties for derived state
|
||||||
help: "",
|
4. Handle side effects in actions
|
||||||
validation: "required"
|
|
||||||
|
### Styling
|
||||||
|
1. Use Tailwind utility classes
|
||||||
|
2. Follow BEM for custom CSS
|
||||||
|
3. Implement responsive design
|
||||||
|
4. Use CSS variables for theming
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
1. Write unit tests for components
|
||||||
|
2. Test store actions and mutations
|
||||||
|
3. Implement E2E tests for critical paths
|
||||||
|
4. Test responsive behavior
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Implementation
|
||||||
|
```typescript
|
||||||
|
const errorHandler = {
|
||||||
|
handleValidationError: (error: ValidationError) => {
|
||||||
|
// Handle validation errors
|
||||||
|
},
|
||||||
|
handleDragError: (error: DragError) => {
|
||||||
|
// Handle drag and drop errors
|
||||||
|
},
|
||||||
|
handleStateError: (error: StateError) => {
|
||||||
|
// Handle state management errors
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
### Form Configuration Structure
|
## Security Considerations
|
||||||
|
|
||||||
|
1. **Input Sanitization**
|
||||||
|
```typescript
|
||||||
|
const sanitizeInput = (input: string): string => {
|
||||||
|
// Sanitization implementation
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Form Validation**
|
||||||
|
```typescript
|
||||||
|
const validateForm = async (form: FormData): Promise<ValidationResult> => {
|
||||||
|
// Validation implementation
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build and Deployment
|
||||||
|
|
||||||
|
### Build Configuration
|
||||||
```javascript
|
```javascript
|
||||||
// Example of a saved form
|
// nuxt.config.ts
|
||||||
{
|
export default defineNuxtConfig({
|
||||||
id: "550e8400-e29b-41d4-a716-446655440000", // UUID
|
// Configuration details
|
||||||
name: "Contact Form",
|
});
|
||||||
description: "",
|
|
||||||
components: [
|
|
||||||
{
|
|
||||||
type: "text",
|
|
||||||
props: {
|
|
||||||
type: "text",
|
|
||||||
name: "name",
|
|
||||||
label: "Name",
|
|
||||||
placeholder: "Enter your name",
|
|
||||||
validation: "required"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "email",
|
|
||||||
props: {
|
|
||||||
type: "email",
|
|
||||||
name: "email",
|
|
||||||
label: "Email",
|
|
||||||
placeholder: "Enter your email",
|
|
||||||
validation: "required,email"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
createdAt: "2025-04-09T03:30:00.000Z"
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Development Setup
|
||||||
|
```bash
|
||||||
|
# Installation
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Development
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Build
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Preview
|
||||||
|
npm run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
For user documentation and usage guidelines, please refer to [Form Builder Documentation](FORM_BUILDER_DOCUMENTATION.md).
|
||||||
|
|
||||||
|
Last updated: April 9, 2025
|
Loading…
x
Reference in New Issue
Block a user