Skip to content

Instantly share code, notes, and snippets.

@KamaKAzii
Last active December 9, 2024 05:13
Show Gist options
  • Save KamaKAzii/445b9222ceee39b3bf4d5f1648f846ea to your computer and use it in GitHub Desktop.
Save KamaKAzii/445b9222ceee39b3bf4d5f1648f846ea to your computer and use it in GitHub Desktop.
Take-Home Project: Dynamic Form Builder
Problem Description:
You are tasked with building a DynamicForm component and a useFormBuilder custom hook. The DynamicForm component should render a dynamic form based on a configuration object, and the useFormBuilder hook should handle the form state and validation logic.
This project will test the candidate's ability to work with advanced TypeScript types to enforce strong typings across dynamic form fields, state, and validation logic.
Requirements:
Create a FieldConfig Type: Each form field should be defined using a FieldConfig type. It must include:
id: string – A unique identifier for the field.
label: string – The field's label.
type: "text" | "number" | "select" | "checkbox" – The type of the field.
options?: string[] – An array of options for select fields.
required: boolean – Whether the field is required.
Additional fields for validation (e.g., min, max for number fields).
Create a FormConfig Type: The FormConfig type should represent an array of FieldConfig objects. Each field's type should dictate the type of its value in the form state.
Create a useFormBuilder Hook:
The hook should take a FormConfig as input and:
Generate the initial form state.
Provide methods to update the state:
setFieldValue(id: string, value: any): void
validateField(id: string): string | null – Returns an error message if validation fails or null if it passes.
validateForm(): Record<string, string | null> – Validates the entire form and returns errors for all fields.
The hook should enforce type safety for field values and validation methods using generics.
Create the DynamicForm Component:
The component should:
Accept a FormConfig and the hook's return value as props.
Render form fields based on the FormConfig.
Include an "onSubmit" button that triggers form validation and logs the form state if validation passes.
Advanced Typing Challenges:
Ensure the type of setFieldValue matches the field’s type dynamically (e.g., setFieldValue should only accept a string for text fields, a number for number fields, etc.).
Use discriminated unions to enforce validation rules based on the type field of FieldConfig.
Bonus Features:
Enhanced Validation:
Support custom validation rules via a validate: (value: any) => string | null property in FieldConfig.
Dynamic Field Types:
Add support for more field types (e.g., radio, file upload) with corresponding typings.
Type-Safe Form State:
Use a mapped type to derive the form state from the FormConfig. For example, if FormConfig includes a text field with id: "name", the form state should have a property name: string.
Tests:
Write unit tests for useFormBuilder to ensure proper state management and validation.
Test the DynamicForm component with edge cases like empty fields, invalid data, and dynamically changing configurations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment