The React Dynamic Form
package provides a powerful and versatile solution for creating dynamic forms in React applications. Designed to simplify the form-building process, this package allows developers to define and manage forms using configuration data with ease. It offers type-safe form handling, ensuring that your forms are robust and reliable. With support for comprehensive validation rules and flexible configuration, this package is ideal for applications that need adaptable and interactive form management. It enables you to leverage TypeScript for safer code while giving you the freedom to create and style custom input types according to your needs.
Install the package using npm:
npm install @bright-lab/react-dynamic-form
The React Dynamic Form
package streamlines the process of creating and managing dynamic forms in React applications. It offers a type-safe, flexible approach to form handling by providing support for:
- Custom Input Types: Define and configure global and form-specific fields with custom render logic to suit various input needs.
- Type Safety: Leverage TypeScript support to ensure that your forms are type-safe, reducing runtime errors and improving code reliability.
- Validation Rules: Implement and customize validation logic to enforce data integrity and user input constraints.
- Dynamic Data Management: Easily handle and integrate dynamic data sources for fields, enabling sophisticated form behaviors and interactions.
- Flexible Rendering: Tailor form rendering and behavior according to your application's specific requirements and styling preferences.
This package is designed to simplify complex form scenarios, enhance development efficiency, and ensure robust form functionality.
First, import the necessary components and types into your application:
Setup your Global fields
import {
DynamicForm,
FormProvider,
IGlobalFieldConfig,
IFieldConfig,
IBaseFieldProps
} from '@bright-lab/react-dynamic-form';
import '@bright-lab/react-dynamic-form/dist/styles.css';
const globalFieldsConfig: IGlobalFieldConfig[] = [
{
type: 'text',
Render: ({ label, name, value, onChange, placeholder, validateField, error } : IBaseFieldProps<string>) => (
<div>
<label>{label}</label>
<input
placeholder="first name"
name={name}
value={value}
onChange={({target}) => onChange(target.value)}
placeholder={placeholder}
onBlur={validateField}
/>
{error && <p>{error}</p>}
</div>
),
},
{
type: 'select',
Render: ({ label, name, value, onChange, validateField, payload, error } : IBaseFieldProps<number>) => {
const [options, setOptions] = React.useState<{ id: number; title: string }[]>([]);
React.useEffect(() => {
const fetchOptions = async () => {
try {
const response = await fetch(payload?.url);
const data = await response.json();
setOptions([{ id: 0, title: 'Select an option' }, ...data]);
} catch (error) {
console.error('Error fetching options:', error);
}
};
fetchOptions();
}, [payload?.url]);
return (
<div>
<p>{label}</p>
<select
name={name}
value={value}
onChange={({target}) => onChange(Number(target.value))}
onBlur={validateField}
>
{options.map((option) => (
<option key={option.id} value={option.id}>
{option.title}
</option>
))}
</select>
{error && <p>{error}</p>}
</div>
);
},
},
// Add more field configurations as needed
];
Set up your form fields and validation rules:
const fields: IFieldConfig<MyFormValues>[] = [
{
label: 'First Name',
type: 'text',
name: 'first_name',
grid: {
xs: 12,
md: 6,
},
validation: [
{
rule: 'required',
message: 'Please enter your first name',
},
{
rule: 'min_length',
params: { length: 3 },
message: 'First name must be at least 3 characters',
},
],
},
{
label: 'Email',
type: 'email',
name: 'email',
grid: {
xs: 12,
md: 6,
},
validation: [
{ rule: 'required', message: 'Email is required' },
{
rule: 'pattern',
params: { regex: '^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$' },
message: 'Invalid email format',
},
],
},
{
label: 'Options',
type: 'select',
name: 'options',
payload: {
url: 'https://jsonplaceholder.typicode.com/todos',
},
validation: [
{
rule: 'required',
message: 'This field is required',
},
],
},
// Add more field configurations as needed
];
Wrap your App with the FormProvider
and use the DynamicForm
component:
function Example() {
interface MyFormValues {
first_name: string;
email: string;
// etc..
}
const initialValues : MyFormValues = {
first_name: 'Chris',
email: 'chris@hotmail.com',
// etc..
};
return (
<FormProvider globalFieldsConfig={globalFieldsConfig}>
<div className="container">
<DynamicForm<MyFormValues>
fields={fields}
initialValues={initialValues}
onChange={(formValues) => console.log('formValues', formValues)}
isError={(value) => console.log('isError', value)}
style={{ rowGap: '16px', columnGap: '16px' }}
/>
</div>
</FormProvider>
);
}
export default Example;
Provides the context for the DynamicForm
component.
-
globalFieldsConfig
: Configuration for global field types.
Renders a form based on the provided field configurations and handles state management.
-
fields
: Configuration for the form fields. -
initialValues
: Initial values for the form fields. -
onChange
: Callback for form value updates. -
isError
: Callback for error state. -
style
: Custom styles. -
className
: Custom class name.
-
IGlobalFieldConfig
: Type for global fields. -
IFieldConfig
: Type for form fields. -
IBaseFieldProps
: Type for renderer field.
This package supports various validation rules to ensure the data entered into the form fields meets the required criteria. Below is a table describing each rule, description and its parameters
Rule | Description | Parameters | Example Usage |
---|---|---|---|
required |
Ensures the field is not empty. | None | { rule: 'required' } |
min |
Validates that the value is greater than or equal to a minimum value. |
value (number) |
{ rule: 'min', params: { value: 5 } } |
max |
Validates that the value is less than or equal to a maximum value. |
value (number) |
{ rule: 'max', params: { value: 10 } } |
number_range |
Validates that the value falls within a specified range. |
min (number), max (number) |
{ rule: 'number_range', params: { min: 5, max: 10 } } |
min_length |
Validates the minimum length of the input. |
length (number) |
{ rule: 'min_length', params: { length: 3 } } |
max_length |
Validates the maximum length of the input. |
length (number) |
{ rule: 'max_length', params: { length: 10 } } |
pattern |
Validates the input against a regular expression. |
regex (RegExp) |
{ rule: 'pattern', params: { regex: '^(?=.*\\d)[0-9+\\- ]*$' } } |
numeric |
Checks if the input is a valid number. | None | { rule: 'numeric' } |
boolean |
Validates if the input is a boolean value (true or false ). |
None | { rule: 'boolean' } |
inclusion |
Ensures the input is one of the specified values. |
values (array of strings) |
{ rule: 'inclusion', params: { values: ['option1', 'option2'] } } |
exclusion |
Ensures the input is not one of the specified values. |
values (array of strings) |
{ rule: 'exclusion', params: { values: ['option1', 'option2'] } } |
The changelog is regularly updated to reflect the changes and updates in each new release.