Dynamic Form Generator in Vue with TypeScript
This challenge focuses on building a dynamic form generator in Vue.js using TypeScript. The goal is to create a component that can render a form based on a JSON schema, allowing for flexible and reusable form creation without hardcoding HTML. This is a common requirement in applications where form structures need to be configurable or driven by external data.
Problem Description
You are tasked with creating a Vue component called DynamicForm that accepts a JSON schema as a prop and dynamically renders a form based on that schema. The schema will define the form fields, their types, validation rules, and labels. The component should generate appropriate input elements (text fields, checkboxes, select dropdowns, etc.) based on the field type specified in the schema. It should also handle basic validation based on the schema.
Key Requirements:
- Schema Input: The component must accept a
schemaprop, which is a JSON object defining the form structure. - Dynamic Rendering: The component must dynamically render form elements based on the
schema. - Input Types: Support at least the following input types:
text,number,checkbox, andselect. You can extend this with more types if you wish. - Labels: Display labels for each field as defined in the schema.
- Validation: Implement basic validation based on the
validationproperty in the schema (e.g.,required,minLength,maxLength,pattern). Display validation errors to the user. - Data Binding: Bind the input values to a
modelprop, which is an object containing the form data. - Event Handling: Emit an
inputevent whenever a form field's value changes, passing the updatedmodelobject.
Expected Behavior:
The DynamicForm component should:
- Receive a
schemaprop and amodelprop. - Render a form with input elements corresponding to the fields defined in the
schema. - Bind the input values to the
modelprop. - Validate the input fields based on the
validationrules in the schema. - Display validation errors if any validation rules are violated.
- Emit an
inputevent with the updatedmodelobject whenever a field's value changes.
Edge Cases to Consider:
- Empty schema: Handle the case where the
schemaprop is empty or invalid. - Missing fields in the schema: Gracefully handle missing fields or properties in the schema.
- Invalid input types: Handle cases where the schema specifies an unsupported input type.
- Complex validation rules: Consider how to handle more complex validation rules beyond the basic examples.
Examples
Example 1:
Input: schema = {
"fields": [
{
"name": "firstName",
"label": "First Name",
"type": "text",
"validation": {
"required": true,
"minLength": 2
}
},
{
"name": "age",
"label": "Age",
"type": "number",
"validation": {
"required": true,
"min": 18,
"max": 120
}
}
]
}
model = {}
Output: A form with two fields: "First Name" (text input) and "Age" (number input). Validation errors are displayed if "First Name" is less than 2 characters or "Age" is not between 18 and 120.
Explanation: The component renders the form based on the schema, binding the input values to the `model` object and applying the specified validation rules.
Example 2:
Input: schema = {
"fields": [
{
"name": "subscribe",
"label": "Subscribe to Newsletter",
"type": "checkbox"
},
{
"name": "country",
"label": "Country",
"type": "select",
"options": ["USA", "Canada", "Mexico"]
}
]
}
model = { subscribe: false, country: '' }
Output: A form with a checkbox for "Subscribe to Newsletter" and a select dropdown for "Country" with options "USA", "Canada", and "Mexico".
Explanation: The component renders a checkbox and a select dropdown based on the schema, binding the values to the `model` object.
Constraints
- Component Structure: The solution must be a Vue component named
DynamicForm. - TypeScript: The code must be written in TypeScript.
- Vue 3: Use Vue 3 and the Composition API.
- Schema Format: The schema must be a JSON object with a
fieldsarray. Each field object must have aname,label,type, and optionallyvalidationandoptionsproperties. - Validation: Focus on implementing
required,minLength,maxLength,min,max, andpatternvalidation rules. - Performance: The component should render efficiently, even with a large number of fields. Avoid unnecessary re-renders.
Notes
- Consider using a library like
vee-validatefor more advanced validation features, but this is not required for this challenge. - Think about how to handle different input types and their corresponding HTML elements.
- Pay attention to data binding and event handling to ensure that the form data is correctly updated and validated.
- Start with a simple schema and gradually add more complexity as you progress.
- Focus on creating a reusable and maintainable component.
- Error handling and graceful degradation are important considerations.