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:
Md Afiq Iskandar 2025-04-23 08:13:34 +08:00
parent 55fb5a9c54
commit 3b4b6437bc
2 changed files with 465 additions and 411 deletions

View File

@ -2,166 +2,208 @@
## 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`**
- Main form builder interface with three-panel layout
- Drag and drop interface for building forms
- Uses empty layout for fullscreen experience
- Contains form name input and save/preview actions
- [View File](pages/form-builder/index.vue)
### Accessing the Form Builder
1. Navigate to `/form-builder` in your browser
2. You'll see a three-panel interface:
- Left: Component Library
- Middle: Form Canvas
- Right: Configuration Panel
2. **`pages/form-builder/manage.vue`**
- Form management interface
- Lists saved forms with search functionality
- Provides edit and delete actions for each form
- Uses empty layout and matches design of main page
- [View File](pages/form-builder/manage.vue)
### Quick Start Guide
1. **Create a New Form**
- Click "New Form" in the header
- Enter a form name and description
- Start adding components
### 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`**
- Left panel component that displays available form elements
- Categorizes components into groups (Basic Inputs, Selection Inputs, etc.)
- Provides search functionality for finding components
- Components can be dragged to the canvas
- Uses Material Design icons
- [View File](components/FormBuilderComponents.vue)
3. **Configure Components**
- Click any component in the canvas to select it
- Use the right panel to configure its properties
- Changes are previewed in real-time
4. **`components/FormBuilderCanvas.vue`**
- Middle panel component that displays the form being built
- Handles drag-and-drop reordering of components
- Renders form elements with preview mode
- Provides selection, deletion, and reordering capabilities
- Uses vuedraggable for drag-and-drop functionality
- [View File](components/FormBuilderCanvas.vue)
4. **Save and Preview**
- Click "Save" to store your form
- Use "Preview" to test the form
- Access saved forms via "Manage Forms"
5. **`components/FormBuilderConfiguration.vue`**
- 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)
## Available Components
6. **`components/ComponentPreview.vue`**
- Renders a preview of form components
- Handles different component types (inputs, headings, paragraphs, etc.)
- Uses FormKit for rendering form inputs
- Provides formatting for non-input elements (headings, paragraphs, dividers)
- [View File](components/ComponentPreview.vue)
### Basic Inputs
Perfect for collecting simple text and numeric data:
- **Text Field**: Single line text input
- Use for: Names, titles, short answers
- Features: Placeholder text, help text, validation
### State Management
- **Text Area**: Multi-line text input
- Use for: Comments, descriptions, long answers
- Features: Resizable, character count option
7. **`stores/formBuilder.js`**
- Pinia store for managing form builder state
- Handles form components, selected component, dragging state
- Provides actions for adding, updating, moving, and deleting components
- Handles form saving and loading with localStorage
- Persists saved forms
- [View File](stores/formBuilder.js)
- **Number**: Numeric input field
- Use for: Age, quantity, numeric values
- Features: Min/max limits, step values
### Utilities
- **Email**: Email address input
- Use for: Contact forms, user registration
- Features: Built-in email validation
8. **`composables/useToast.js`**
- Toast notification composable for consistent toast messages
- Wraps Vue Toastification with standardized configurations
- Provides success, error, warning, and info methods
- [View File](composables/useToast.js)
- **Password**: Secure password input
- Use for: Login forms, security inputs
- Features: Password masking, strength indicators
## 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
- Drag-and-drop interface for adding components to the form
- Reordering components via drag-and-drop
- Configuring component properties (labels, placeholders, validation, etc.)
- Real-time preview of the form being built
- **Checkbox Group**: Multiple choice selection
- Use for: Multiple selections, preferences
- Features: Select all, option layout control
### Component Types
- **Basic Inputs**: Text, Textarea, Number, Email, Password
- **Selection Inputs**: Select, Checkbox, Radio
- **Date and Time**: Date Picker, Time Picker, Date & Time
- **Advanced**: File Upload, Repeater, Group
- **Layout**: Heading, Paragraph, Divider
- **Radio Group**: Single choice selection
- Use for: Exclusive choices, yes/no questions
- Features: Button or traditional style
### Form Management
- Save forms to localStorage
- List all saved forms
- Search for forms by name
- Edit existing forms
- Delete forms
### Date and Time
Temporal input components:
- **Date Picker**: Date selection
- Use for: Birthdays, scheduling
- Features: Date range limits, format options
- **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
- Built-in validation options (required, email, min, max, etc.)
- Quick validation buttons
- Validation rule syntax help
- Required field checkbox
1. Validate on the appropriate event
2. Provide clear error messages
3. Show validation status clearly
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
- 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
## Managing Forms
## Implementation Details
### Saved Forms
- View all forms in the management interface
- Search and filter forms
- Duplicate existing forms
- Archive unused forms
### Layout Structure
- Header with navigation and primary actions
- Form name input section
- Three-panel main content area
- Preview modal for testing the form
### Form Actions
- Preview: Test the form
- Edit: Modify form structure
- Delete: Remove unused forms
- Export: Save form configuration
### State Management
- Centralized Pinia store for form state
- Computed properties for derived state
- Watchers for reactivity
- Local storage for persistence
### Form Analytics
- View submission statistics
- Track completion rates
- Identify problem fields
- Monitor usage patterns
### Component Communication
- Props for parent-to-child data flow
- Events for child-to-parent communication
- Store actions for cross-component communication
## Troubleshooting
### Styling
- Tailwind CSS for utility-first styling
- Custom transitions and animations
- Responsive breakpoints
- Consistent color scheme
### Common Issues
1. **Form Not Saving**
- Check your connection
- Ensure form has a name
- 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
2. Add components by dragging them from the left panel to the canvas
3. Select a component on the canvas to configure it in the right panel
4. Save the form using the Save button in the header
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
3. **Validation Not Working**
- Verify validation rules syntax
- Check field names are unique
- Ensure validation is enabled
## Development Notes
- The form builder uses vuedraggable for drag-and-drop functionality
- FormKit is used for all form inputs
- Material Design icons are used throughout
- 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
### Getting Help
- Check the technical documentation
- Contact support team
- Submit bug reports
- Request features
---
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

View File

@ -1,46 +1,140 @@
# 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)
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)
## Architecture Overview
## 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/
├── form-builder/
│ ├── index.vue # Main form builder page
│ └── manage.vue # Form management page
│ ├── index.vue # Main builder interface
│ └── manage.vue # Form management
components/
├── FormBuilderComponents.vue # Left panel components
├── FormBuilderCanvas.vue # Middle panel canvas
├── FormBuilderConfiguration.vue # Right panel configuration
└── ComponentPreview.vue # Component rendering
├── FormBuilderComponents.vue # Component library
├── FormBuilderCanvas.vue # Form canvas
├── FormBuilderConfiguration.vue # Component config
└── ComponentPreview.vue # Preview renderer
stores/
└── formBuilder.js # State management
composables/
└── 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
### 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', {
state: () => ({
state: (): FormState => ({
formComponents: [],
selectedComponentId: null,
formName: 'New Form',
@ -50,297 +144,215 @@ export const useFormBuilderStore = defineStore('formBuilder', {
}),
getters: {
selectedComponent: (state) => {
return state.selectedComponentId
? 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()
};
}
selectedComponent: (state) => // Implementation
formConfig: (state) => // Implementation
},
actions: {
addComponent(component) {
const newComponent = {
...component,
id: uuidv4(),
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']
addComponent(component: FormComponent) // Implementation
updateComponent(id: string, updates: Partial<FormComponent>) // Implementation
deleteComponent(id: string) // Implementation
moveComponent(oldIndex: number, newIndex: number) // Implementation
}
});
```
## 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
<!-- FormBuilderCanvas.vue -->
<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>
```
interface InputComponent extends BaseComponent {
props: InputComponentProps;
}
### Drag Start Handler
interface SelectComponent extends BaseComponent {
props: SelectComponentProps;
}
```javascript
// 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"
/>
// Additional type definitions...
```
## 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:
```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>
const validateField = (value: any, rules: string) => {
// Validation implementation
};
```
### Available Validators
## Grid System
```javascript
const availableValidators = [
{ name: 'required', label: 'Required' },
{ name: 'email', label: 'Email' },
{ name: 'url', label: 'URL' },
{ name: 'number', label: 'Number' },
{ name: 'min:5', label: 'Min Length/Value' },
{ name: 'max:100', label: 'Max Length/Value' },
{ name: 'between:5,10', label: 'Between Range' },
{ 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',
// ...
### Implementation
```typescript
const gridSystem = {
columns: 12,
breakpoints: {
sm: 640,
md: 768,
lg: 1024,
xl: 1280
},
// ...
];
calculateSpan: (width: number) =>
Math.min(Math.max(1, Math.round(width * 12)), 12)
};
```
## Responsive Design
## Event Handling
### Responsive Layout
The form builder uses a responsive layout that adapts to different screen sizes:
```vue
<!-- pages/form-builder/index.vue -->
<div class="flex-1 flex flex-col lg:flex-row overflow-hidden">
<!-- Left Panel -->
<div class="lg:w-1/4 border-r border-gray-200 bg-white overflow-hidden flex flex-col">
<!-- 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>
### Component Events
```typescript
const componentEvents = {
onAdd: (event: DragEvent) => void;
onUpdate: (event: UpdateEvent) => void;
onSelect: (id: string) => void;
onDelete: (id: string) => void;
onDuplicate: (id: string) => void;
onValidate: (component: FormComponent) => ValidationResult;
};
```
### Responsive Header
## Performance Optimization
```vue
<header class="bg-gray-800 p-2 flex flex-wrap items-center justify-between text-white">
<div class="flex items-center mb-2 sm:mb-0 gap-4">
<!-- Logo and back button -->
</div>
<div class="flex flex-wrap items-center space-x-2">
<!-- Actions -->
</div>
</header>
### Implementation Details
1. **Component Lazy Loading**
```typescript
const ComponentPreview = defineAsyncComponent(() =>
import('./ComponentPreview.vue')
);
```
## 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
// Example of a form component object
{
id: "550e8400-e29b-41d4-a716-446655440000", // UUID
type: "text",
name: "Text Field",
category: "Basic Inputs",
icon: "material-symbols:text-fields",
props: {
type: "text",
name: "text_1",
label: "Text Field 1",
placeholder: "Enter text...",
help: "",
validation: "required"
## Development Guidelines
### Component Development
1. Follow Vue 3 Composition API patterns
2. Implement proper TypeScript types
3. Use props validation
4. Emit typed events
5. Document component API
### State Management
1. Use Pinia for global state
2. Implement proper actions and getters
3. Use computed properties for derived state
4. Handle side effects in actions
### 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
// Example of a saved form
{
id: "550e8400-e29b-41d4-a716-446655440000", // UUID
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"
}
```
// nuxt.config.ts
export default defineNuxtConfig({
// Configuration details
});
```
### 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