155 lines
4.3 KiB
Markdown
155 lines
4.3 KiB
Markdown
|
|
# Reusable Field Components
|
||
|
|
|
||
|
|
This document explains how to use the reusable field components created for consistent UI across different data types.
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
We've created a set of reusable Angular components for different field types:
|
||
|
|
- Text Field
|
||
|
|
- Number Field
|
||
|
|
- Phone Number Field
|
||
|
|
- Paragraph Field
|
||
|
|
- Password Field
|
||
|
|
- Textarea Field
|
||
|
|
|
||
|
|
Each component follows the same pattern and uses ThemeService for consistent styling.
|
||
|
|
|
||
|
|
## Field Configuration
|
||
|
|
|
||
|
|
All field components use a common `FieldConfig` interface:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
interface FieldConfig {
|
||
|
|
name: string; // Unique field name
|
||
|
|
label: string; // Display label
|
||
|
|
type: string; // Field type (text, number, phone, etc.)
|
||
|
|
required?: boolean; // Is field required?
|
||
|
|
placeholder?: string; // Placeholder text
|
||
|
|
description?: string; // Helper text
|
||
|
|
// Additional type-specific properties
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Component Usage
|
||
|
|
|
||
|
|
### 1. Text Field
|
||
|
|
```html
|
||
|
|
<app-text-field
|
||
|
|
[field]="{ name: 'username', label: 'Username', type: 'text', required: true }"
|
||
|
|
[value]="formData.username"
|
||
|
|
(valueChange)="formData.username = $event">
|
||
|
|
</app-text-field>
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Number Field
|
||
|
|
```html
|
||
|
|
<app-number-field
|
||
|
|
[field]="{ name: 'age', label: 'Age', type: 'number', min: 0, max: 120 }"
|
||
|
|
[value]="formData.age"
|
||
|
|
(valueChange)="formData.age = $event">
|
||
|
|
</app-number-field>
|
||
|
|
```
|
||
|
|
|
||
|
|
### 3. Phone Field
|
||
|
|
```html
|
||
|
|
<app-phone-field
|
||
|
|
[field]="{ name: 'phone', label: 'Phone Number', type: 'phone', pattern: '^\\+?[1-9]\\d{1,14}$' }"
|
||
|
|
[value]="formData.phone"
|
||
|
|
(valueChange)="formData.phone = $event">
|
||
|
|
</app-phone-field>
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. Paragraph Field
|
||
|
|
```html
|
||
|
|
<app-paragraph-field
|
||
|
|
[field]="{ name: 'description', label: 'Description', type: 'paragraph', rows: 6, showCharacterCount: true }"
|
||
|
|
[value]="formData.description"
|
||
|
|
(valueChange)="formData.description = $event">
|
||
|
|
</app-paragraph-field>
|
||
|
|
```
|
||
|
|
|
||
|
|
### 5. Password Field
|
||
|
|
```html
|
||
|
|
<app-password-field
|
||
|
|
[field]="{ name: 'password', label: 'Password', type: 'password', showStrengthIndicator: true }"
|
||
|
|
[value]="formData.password"
|
||
|
|
(valueChange)="formData.password = $event">
|
||
|
|
</app-password-field>
|
||
|
|
```
|
||
|
|
|
||
|
|
### 6. Textarea Field
|
||
|
|
```html
|
||
|
|
<app-textarea-field
|
||
|
|
[field]="{ name: 'comments', label: 'Comments', type: 'textarea', rows: 4 }"
|
||
|
|
[value]="formData.comments"
|
||
|
|
(valueChange)="formData.comments = $event">
|
||
|
|
</app-textarea-field>
|
||
|
|
```
|
||
|
|
|
||
|
|
## Dynamic Form Component
|
||
|
|
|
||
|
|
For easier usage, we've created a `DynamicFormComponent` that can render multiple fields based on configuration:
|
||
|
|
|
||
|
|
```html
|
||
|
|
<app-dynamic-form
|
||
|
|
[fields]="formFields"
|
||
|
|
[formData]="formData"
|
||
|
|
(formSubmit)="onSubmit($event)"
|
||
|
|
(formCancel)="onCancel()">
|
||
|
|
</app-dynamic-form>
|
||
|
|
```
|
||
|
|
|
||
|
|
In your component:
|
||
|
|
```typescript
|
||
|
|
formFields = [
|
||
|
|
{ name: 'name', label: 'Name', type: 'text', required: true },
|
||
|
|
{ name: 'email', label: 'Email', type: 'text', required: true },
|
||
|
|
{ name: 'age', label: 'Age', type: 'number', min: 0 },
|
||
|
|
{ name: 'phone', label: 'Phone', type: 'phone' },
|
||
|
|
{ name: 'bio', label: 'Bio', type: 'paragraph' }
|
||
|
|
];
|
||
|
|
|
||
|
|
formData = {};
|
||
|
|
|
||
|
|
onSubmit(data) {
|
||
|
|
console.log('Form submitted:', data);
|
||
|
|
// Handle form submission
|
||
|
|
}
|
||
|
|
|
||
|
|
onCancel() {
|
||
|
|
console.log('Form cancelled');
|
||
|
|
// Handle form cancellation
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Benefits of This Approach
|
||
|
|
|
||
|
|
1. **Consistency**: All fields follow the same styling and behavior patterns
|
||
|
|
2. **Maintainability**: Changes to one field type automatically apply everywhere
|
||
|
|
3. **Reusability**: Components can be used across different forms and modules
|
||
|
|
4. **Extensibility**: Easy to add new field types following the same pattern
|
||
|
|
5. **Theme Support**: All components use ThemeService for consistent theming
|
||
|
|
6. **Validation**: Built-in validation support for each field type
|
||
|
|
7. **Accessibility**: Proper labeling and ARIA attributes
|
||
|
|
|
||
|
|
## Adding New Field Types
|
||
|
|
|
||
|
|
To add a new field type:
|
||
|
|
|
||
|
|
1. Create a new component that extends `BaseFieldComponent`
|
||
|
|
2. Implement the template and logic specific to that field type
|
||
|
|
3. Add the component to the `FieldTypesModule`
|
||
|
|
4. Register it in the `FieldFactoryService`
|
||
|
|
5. Update the documentation
|
||
|
|
|
||
|
|
## Styling
|
||
|
|
|
||
|
|
All field components use the shared SCSS file which provides:
|
||
|
|
- Consistent spacing and typography
|
||
|
|
- ThemeService integration for colors
|
||
|
|
- Responsive design patterns
|
||
|
|
- Proper focus states and hover effects
|
||
|
|
- Error state styling
|
||
|
|
- Accessibility considerations
|
||
|
|
|
||
|
|
The styling follows the same patterns used in the UI enhancement rules we established earlier.
|