Hone logo
Hone
Problems

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 schema prop, 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, and select. 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 validation property in the schema (e.g., required, minLength, maxLength, pattern). Display validation errors to the user.
  • Data Binding: Bind the input values to a model prop, which is an object containing the form data.
  • Event Handling: Emit an input event whenever a form field's value changes, passing the updated model object.

Expected Behavior:

The DynamicForm component should:

  1. Receive a schema prop and a model prop.
  2. Render a form with input elements corresponding to the fields defined in the schema.
  3. Bind the input values to the model prop.
  4. Validate the input fields based on the validation rules in the schema.
  5. Display validation errors if any validation rules are violated.
  6. Emit an input event with the updated model object whenever a field's value changes.

Edge Cases to Consider:

  • Empty schema: Handle the case where the schema prop 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 fields array. Each field object must have a name, label, type, and optionally validation and options properties.
  • Validation: Focus on implementing required, minLength, maxLength, min, max, and pattern validation 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-validate for 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.
Loading editor...
typescript