Vue Form State Management with TypeScript
This challenge focuses on building a reusable component in Vue.js that manages the state of a form, including input values, validation errors, and submission status. Effective form state management is crucial for building complex and user-friendly applications, and this exercise will solidify your understanding of Vue's reactivity and TypeScript's type safety.
Problem Description
You are tasked with creating a Form component that encapsulates form state management. This component should accept an array of form fields as props, each field having a name, type, initial value, and validation rules. The component should:
- Maintain State: Store the value of each form field in its internal state.
- Handle Input Changes: Update the state whenever an input field's value changes.
- Validate Fields: Validate each field based on the provided validation rules whenever the value changes. Validation rules will be simple strings (e.g., "required", "email"). For this challenge, implement basic validation: "required" means the field cannot be empty. "email" means the field must be a valid email address.
- Display Errors: Display validation errors next to the corresponding input fields.
- Handle Submission: Provide a method (
submitForm) that can be called to trigger form submission. This method should return an object containing the form data and any validation errors. - Track Submission Status: Maintain a submission status (e.g., "idle", "submitting", "success", "error").
Key Requirements:
- The component must be written in TypeScript.
- The component should be reusable and configurable through props.
- The validation logic should be encapsulated within the component.
- The component should provide a clear and concise API for interacting with the form.
Expected Behavior:
- When the component is initialized, the input fields should be populated with their initial values.
- As the user types in the input fields, the state should be updated in real-time.
- Validation errors should be displayed immediately after the user leaves a field.
- When
submitFormis called, the component should:- Validate all fields.
- Collect the form data.
- Return an object containing the form data and an array of validation errors (if any).
- Set the submission status to "submitting".
- After a short delay (e.g., 1 second), set the submission status to "success" or "error" (for simplicity, assume success always).
Examples
Example 1:
Input:
fields: [
{ name: 'name', type: 'text', initialValue: '', validation: 'required' },
{ name: 'email', type: 'email', initialValue: '', validation: 'required, email' }
]
Output (after user enters invalid data):
{
"data": {
"name": "",
"email": "invalid-email"
},
"errors": [
{ field: 'name', message: 'This field is required' },
{ field: 'email', message: 'This field is required' },
{ field: 'email', message: 'This field must be a valid email address' }
]
}
Explanation: The name field is empty, triggering the "required" validation error. The email field contains an invalid email address, triggering both the "required" and "email" validation errors.
Example 2:
Input:
fields: [
{ name: 'username', type: 'text', initialValue: 'testuser', validation: '' }
]
Output (after user submits the form):
{
"data": {
"username": "testuser"
},
"errors": []
}
Explanation: The username field is valid (no validation rules are specified), so no errors are returned.
Constraints
- Validation Rules: Only implement "required" and "email" validation rules.
- Email Validation: Use a simple regex for email validation:
/^[^\s@]+@[^\s@]+\.[^\s@]+$/. - Submission Delay: Simulate a 1-second submission delay.
- Error Messages: Use clear and concise error messages.
- Component Structure: The component should be well-structured and easy to understand.
- TypeScript: Strictly adhere to TypeScript best practices.
Notes
- Consider using Vue's
v-modeldirective for two-way data binding. - Think about how to handle multiple validation rules for a single field.
- Focus on creating a reusable and maintainable component.
- You don't need to implement actual form submission to a server; just simulate it.
- The
typeproperty of the field is not used for validation in this challenge, but it could be used for rendering different input types in a more complete implementation. - Assume the input fields will be rendered within the component's template. You don't need to worry about the actual HTML rendering of the input fields themselves, just the state management and validation logic.