Hone logo
Hone
Problems

React Form Builder: Dynamic Form Generation

This challenge asks you to build a dynamic form builder component in React using TypeScript. This is a fundamental building block for many web applications, enabling users to create custom forms for data collection, surveys, and more without needing to write code.

Problem Description

You are tasked with creating a React component, FormBuilder, that allows users to dynamically add, configure, and arrange various form input fields. The component should manage the state of the form elements and render them based on user input.

Key Requirements:

  1. Add New Fields: Users should be able to add new form fields of different types (e.g., Text Input, Textarea, Checkbox, Radio Button, Select).
  2. Field Configuration: Each added field should have configurable properties such as:
    • label: The text displayed next to the input.
    • type: The type of input (e.g., 'text', 'textarea', 'checkbox', 'radio', 'select').
    • placeholder: Placeholder text for text-based inputs.
    • options: For 'radio' and 'select' types, an array of available options (each option should have a value and label).
    • required: A boolean indicating if the field is mandatory.
  3. Field Reordering: Users should be able to reorder the form fields.
  4. Field Deletion: Users should be able to remove individual form fields.
  5. Form Rendering: The FormBuilder component should render the configured form elements.
  6. State Management: The component must effectively manage the state of all added form fields and their configurations.
  7. TypeScript: The solution must be implemented entirely in TypeScript, ensuring type safety.

Expected Behavior:

  • The FormBuilder component should display a set of controls to add new fields.
  • When a new field is added, it should appear in the builder with its default configuration.
  • Users should be able to edit the properties of each field (label, type, options, etc.) through an intuitive interface within the builder.
  • Drag-and-drop or up/down arrow functionality should be provided for reordering fields.
  • A delete button should be present for each field.
  • The FormBuilder should also provide a way to preview or generate the actual HTML form structure based on the current configuration.

Edge Cases to Consider:

  • Empty form state: What happens when no fields are added?
  • Complex option configurations for radio/select.
  • Handling of validation for required fields (this can be basic: just marking them as required visually, or a more advanced implementation where the generated form validates). For this challenge, focus on marking visually.
  • User interface for editing configurations: How to present the configuration options for each field in a user-friendly way.

Examples

Example 1: Initial State and Adding Fields

Input (Conceptual):
User clicks "Add Text Input" button.

Output (Conceptual - How the builder might look/behave):
The FormBuilder UI now displays a Text Input field with default settings:
- Label: "New Text Input"
- Type: "text"
- Placeholder: ""
- Required: false

User then clicks "Add Select" button.

The FormBuilder UI now displays:
1. Text Input field (as above)
2. Select field with default settings:
   - Label: "New Select"
   - Type: "select"
   - Options: []
   - Required: false

Example 2: Configuring and Reordering Fields

Input (Conceptual):
Current form fields:
1. Text Input (Label: "Name", Required: true)
2. Select (Label: "Country", Options: [{value: "US", label: "United States"}, {value: "CA", label: "Canada"}])

User edits the Text Input:
- Changes Label to "Full Name"
- Sets Required to false

User drags the Select field above the Text Input field.

Output (Conceptual - How the builder UI updates):
The FormBuilder UI now displays:
1. Select field (Label: "Country", Options: [{value: "US", label: "United States"}, {value: "CA", label: "Canada"}], Required: false)
2. Text Input field (Label: "Full Name", Required: false)

Example 3: Deleting a Field

Input (Conceptual):
Current form fields:
1. Text Input (Label: "Email")
2. Checkbox (Label: "Subscribe to newsletter")

User clicks the delete button next to the Checkbox field.

Output (Conceptual - How the builder UI updates):
The FormBuilder UI now displays:
1. Text Input (Label: "Email")

Constraints

  • The primary implementation must be within React functional components using Hooks.
  • State management should be handled using useState or useReducer. For more complex state, consider a dedicated state management library if preferred, but useState for individual fields and an array of fields is sufficient for this challenge.
  • Styling can be basic (e.g., CSS Modules, inline styles) and is not the primary focus. Focus on functionality.
  • The generated form output should be a standard HTML <form> element with appropriate <input>, <textarea>, <select>, and <label> tags.
  • Consider performance implications for large numbers of form fields, although extreme optimization is not required.

Notes

  • Think about the data structure you will use to represent each form field. An array of objects, where each object describes a field's properties, is a good starting point.
  • Consider how you will manage the unique identification of each form field (e.g., using a UUID or a simple counter).
  • The interface for adding and configuring fields should be clear and intuitive. You might want to use modal dialogs or inline editing.
  • For field types like "Radio" and "Select", a sub-component or a dedicated configuration interface for managing their options will be necessary.
  • You'll need to define TypeScript interfaces for your form field configurations.
  • The challenge is to build the builder component. The actual submission logic of the generated form is out of scope.
Loading editor...
typescript