Dynamic Forms

How to use Dynamic Forms Custom Hook to speed up building simple forms.

Basic Usage

Import the hook, define the DynamicFormSections and render the form.

1
2const Component: React.FC = () => {
3    const sections: DynamicFormSection[] = [
4        {
5            title: "Login",
6            key: "section-1-login",
7            items: [
8                {
9                    key: "name",
10                    label: "Name",
11                    controlType: "Text",
12                },
13                {
14                    key: "email",
15                    label: "Email",
16                    placeholder: "name@domain.com",
17                    controlType: "Text",
18                },
19                {
20                    key: "user-accepted",
21                    label: "I understand",
22                    initialValue: true,
23                    controlType: "Checkbox",
24                },
25            ],
26        },
27    ];
28
29    const { renderForm } = useDynamicForm(sections);
30
31    return <div>{renderForm()}</div>;
32};
33                    

Login


Conditional rendering example

Every form element can be hidden based on any condition you define yourself. Simply set the visibility for that key as shown in the code snippet below.

1
2const ComponentConditionalRender: React.FC = () => {
3    const sections: DynamicFormSection[] = [
4        {
5            title: "Extra Info",
6            key: "section-2-extra-info",
7            items: [
8                {
9                    key: "have-additional-info",
10                    label: "I have additional information",
11                    controlType: "Checkbox",
12                },
13                {
14                    key: "info",
15                    placeholder: "Additional information",
16                    controlType: "Text",
17                },
18            ],
19        },
20    ];
21
22    const { 
23        renderForm, 
24        meta: {
25            "section-2-extra-info": {
26                "have-additional-info": { hasTruthyValue }
27            }
28        }, 
29        setHidden,
30    } = useDynamicForm(sections);
31
32    useEffect(() => {
33        setHidden("section-2-extra-info", "info", !hasTruthyValue)
34    }, [hasTruthyValue])
35
36    return <div>{renderForm()}</div>;
37};
38                    

Extra Info


Form errors example

Every form element defined can display an error message based on any validation rules you define yourself. Simply set the indicator for that key as shown in the code snippet below.

1
2const FormWithErrors: React.FC = () => {
3    const sections: DynamicFormSection[] = [
4        {
5            key: "section",
6            items: [
7                {
8                    key: "field",
9                    description: "This is a mandatory field, but it shouldn't be too long",
10                    controlType: "Text",
11                },
12            ],
13        },
14    ];
15
16    const {
17        renderForm,
18        state: {
19            "section": {
20                "field": value
21            }
22        },
23        setIndicator
24    } = useDynamicForm(sections);
25
26    useEffect(() => {
27        let indicator: Indicator = {
28            type: "success",
29            message: "Perfect :)"
30        };
31        if (!value) {
32            indicator = {
33                type: "danger",
34                message: "Please fill in this field!"  
35            }
36        } else if ((value as string)?.length > 15) {
37            indicator = {
38                type: "warning",
39                message: "Too long :("  
40            }
41        }
42
43        setIndicator("section", "field", indicator);
44    }, [value]);
45
46    return (
47            <div>{renderForm()}</div>
48    );
49};
50                    

This is a mandatory field, but it shouldn't be too long


Dynamic forms API

useDynamicForm

type DynamicFormInternalStateValue = string | string[] | Date | boolean | number | null;

type DynamicFormMetaDataItem = { isVisible: boolean; hasIndicator: boolean; hasTruthyValue: boolean; }

Property nameValue typeInfo
renderForm

() => JSX.Element
                                
The callback function which will render the entire form.
state

[k: string]: {
    [k: string]: DynamicFormInternalStateValue;
};
                                
The current state of the form.
patchState

(section: string, key: string, value: DynamicFormInternalStateValue) => void;
A helper utility to change the value of a particular item.
setIndicator

(section: string, key: string, indicator: FeedbackIndicatorProps) => void;
A helper utility to set a feedback indicator of a particular item.
setHidden

(section: string, key: string, hidden: boolean) => void;
A helper utility to set visibility of a particular item.
meta

[k: string]: {
    [k: string]: DynamicFormMetaDataItem;
};
                                
The metadata of each current field value in the form. Shows if each field is visible, has an indicator active or has a truthy value.
info

{ dirty: boolean; hasIndicators: boolean; isAllTruthy: boolean; }
                                
Additional information about current state of the form.

DynamicFormSection

Property nameOptionalValue typeInfo
keystringRequired unique id of this element
titlestringThe title of the header of the section
itemsArray<DynamicFormItem>The form items that belong to that section.
wrappingElement"div" | "section" | "none"The wrapping element (if any) for the form items of that section. Defaut: "none"'.
additionalProps{ [k: string]: any; }Any additional element props to be mapped to the wrappingElement (if one is enabled).

DynamicFormItem

Property nameOptionalValue typeInfo
keystringRequired unique id of this element
controlType"Hidden" | "Text" | "Textarea" | "Checkbox" | "Dropdown" | "Datepicker" | "Radio" | "Option" | "ErrorLabel" | "Stepper"Required type of element (or control). Default: "Text".
initialValuestring | string[] | Date | boolean | number | nullOptional initial value of the element when it gets created.
labelstringAn optional label displayead above the form field.
descriptionstringAn optional description displayed below the label and above the form field.
multibooleanThis will enable 'multiple' property for the Dropdown component
minnumber | Date

The 'min' property which will applied to the following components: Stepper, Datepicker

This will also apply the 'minLength' property of Text and TextArea

maxnumber | Date

The 'max' property which will applied to the following components: Stepper, Datepicker

This will also apply the 'maxLength' property of Text and TextArea

placeholderstringThe 'placeholder' property which will applied to the following components: Text, Textarea
optionsArray<DynamicFormOption>Defines all the available options for the following components: Dropdown, Radio, Option
formElementAdditionalProps{ [k: string]: any; }Any additional element props to be mapped to the element. Depends on the controlType. Must be a valid prop for that element.
wrappingElement"div" | "section" | "none"The wrapping element (if any) for the form item. It wraps the label, element, error message and description in the chosen element. Defaut: "none"'.
additionalProps{ [k: string]: any; }Any additional element props to be mapped to the wrappingElement (if one is enabled).

DynamicFormOption<T = any>

Property nameOptionalValue typeInfo
keystringRequired unique id of this option
valueTThe value of the option.
labelstringThe label of the option.
descriptionstringAn optional description displayed below the label for the Radio component.
additionalProps{ [k: string]: any; }Any additional element props to be mapped to the underlying option element. Depends on the controlType. Must be a valid prop for that element.