Hone logo
Hone
Problems

Dynamic Form Builder in Angular

This challenge involves creating a flexible form builder component in Angular. The goal is to enable users to dynamically construct forms by selecting and configuring various input types, all managed through a user-friendly interface. This is a fundamental feature for many web applications, allowing for user-generated content and customizable data collection.

Problem Description

Your task is to develop an Angular component that allows users to build forms on the fly. This form builder should support a predefined set of input field types (e.g., text input, textarea, select dropdown, checkbox, radio button). Users should be able to add new fields, configure their properties (label, placeholder, options for select/radio, required status), and arrange them within the form. The builder should also be able to render the generated form and provide a way to access its data.

Key Requirements:

  • Field Types: Support at least the following field types:
    • Text Input (<input type="text">)
    • Textarea (<textarea>)
    • Select Dropdown (<select>)
    • Checkbox (<input type="checkbox">)
    • Radio Button (<input type="radio">)
  • Field Configuration: For each field type, users should be able to configure:
    • Label: The text displayed next to the input.
    • Placeholder: The hint text within the input (for text and textarea).
    • Options: For select dropdowns and radio buttons, a list of key-value pairs for the options.
    • Required: A boolean indicating if the field is mandatory.
  • Dynamic Addition: Users should be able to select a field type from a list and add it to the form.
  • Form Rendering: The component should be able to render the dynamically built form using Angular's reactive forms capabilities.
  • Data Submission: A mechanism to retrieve the data from the rendered form when it's submitted.
  • User Interface: A clean and intuitive UI for adding and configuring fields.

Expected Behavior:

  1. The user sees an interface with options to add new form fields.
  2. When a user selects a field type (e.g., "Text Input"), a new input field appears in a "configuration panel" or directly in a preview area.
  3. The user can then edit the properties of this new field (label, placeholder, etc.).
  4. For select and radio fields, the user can add, remove, and edit individual options.
  5. The dynamically built form is displayed in a separate "preview" or "rendered form" area.
  6. When the rendered form is submitted, the collected data should be accessible.

Edge Cases:

  • Handling empty or invalid configurations for fields.
  • Ensuring correct data types are handled during submission (e.g., boolean for checkboxes).
  • Managing the order of fields in the form.

Examples

Example 1: Adding and Configuring a Text Input

Input: User clicks "Add Text Input". User enters "Your Name" for the Label. User enters "Enter your full name" for the Placeholder. User checks the "Required" checkbox.

Output (Conceptual UI State):

  • A text input field appears in the rendered form with the label "Your Name".
  • The input field has the placeholder "Enter your full name".
  • The input field is marked as required.

Example 2: Adding and Configuring a Select Dropdown

Input: User clicks "Add Select". User enters "Choose an Option" for the Label. User adds the following options: * Key: "apple", Value: "Apple" * Key: "banana", Value: "Banana" * Key: "cherry", Value: "Cherry" User checks the "Required" checkbox.

Output (Conceptual UI State):

  • A select dropdown appears in the rendered form with the label "Choose an Option".
  • The dropdown has three options: "Apple", "Banana", and "Cherry".
  • The field is marked as required.

Example 3: Submitting Form Data

Input: A form has been built with:

  1. Text Input: Label="Email", Placeholder="your.email@example.com", Required=true
  2. Select Dropdown: Label="Country", Options=[{key: "us", value: "USA"}, {key: "ca", value: "Canada"}], Required=false

User fills the rendered form:

  • Email: "test@example.com"
  • Country: "USA"

User clicks the submit button.

Output: A JSON object representing the form data:

{
  "email": "test@example.com",
  "country": "us"
}

Explanation: The keys used in the JSON output should ideally be derived from the field labels or a generated unique identifier. For simplicity, assume they are derived from lowercase, slugified labels or unique IDs.

Constraints

  • The form builder should be implemented using Angular.
  • The solution must use TypeScript.
  • Angular's reactive forms module (@angular/forms) should be utilized for rendering and handling form data.
  • The solution should be efficient enough to handle forms with up to 20 fields without significant performance degradation.
  • User input for field properties should be validated where appropriate (e.g., ensuring options for select/radio have both key and value).

Notes

  • Consider how you will manage the state of the form being built. An array of field configurations is a common approach.
  • For the rendered form, you'll need to dynamically create form controls based on the configuration.
  • Think about how you will generate unique identifiers for each field if needed for internal management or data keys.
  • You might want to use a component-based approach, with a main FormBuilderComponent and potentially child components for each field type's configuration and rendering.
  • For the "Options" in select/radio fields, consider how the user will add, remove, and reorder these options within the builder interface.
Loading editor...
typescript