A generic form renderer with Typescript, hooks, and styled components.
With a single JSON object to define your form, gotta-go-form's Form component will render out an entire form with validation, and field dependencies.
Gotta Go Form's goal is to allow quick creation of forms with even the most complicated requirements.
#Yarn
yarn add gotta-go-form
#NPM
npm install gotta-go-form
import {Form, FormType} from 'gotta-go-form'
render() {
const input: FormField = {
title: "Input",
accessor: "input",
type: FormType.Input,
callback: e => console.log(e.target.value),
value: "",
mandatoryMessage: "please put something here",
properties: { inputProps: { maxLength: 5 } }
};
let def: FormDefinition = {
sections: [
{
title: "Landing Zone",
fields: [input]
}
]
};
let footeractions = [
{
text: "Submit",
type: "Primary",
validate: true,
onClick: () => console.log("Submitted")
}
];
return <Form formDefinition={def} footerActions={footeractions} />;
}
The object used to define your form is defined as a list of "Sections" which in turn are defined as a list of "FormFields"
interface FormDefinition {
sections: Section[];
}
interface Section {
title: string;
fields: FormField[];
}
The Form Field object represents a single field on your form. gotta-go-form currently supports the following field types:
- Input
- Checkbox
- DropDown
- RadioButtonList
- CheckboxList
- DateTime
- TextArea
- Slider
- Custom
It is defined using the following interface:
interface FormField {
title: string; //the name of your field
accessor: string; //the unique identifier of your field
type: FormType;
callback?: (e: any) => void; //the function to be called on change of your field
value?: any;
options?: FormOptions[]; //the potential values of your field (used by DropDown, RadioButtonList, and CheckBoxList)
properties?: any; //optional properties specific to your field type i.e. the format of your datetime picker
customComponent?: (field: FormField) => JSX.Element;
mandatoryMessage?: string;
validation?: Validation | Validation[];
visibility?: Visibility;
observer?: Observer;
fieldWidthPercentage?: number; // the percentage of the row you want this field to take up. Default is 100.
}
interface FormOptions {
value: number | string;
label: string;
}
It is important that every field in your form has a unique accessor The accessor property is the field the form uses to distinguish fields in your form. Think of it like an ID on a DOM object.
You can find examples of the different form types here
Each field type has valid properties that are specific to it
Field Type | Properties |
---|---|
Input | inputProps |
TextArea | inputProps |
CheckBox | N/A |
DropDown | All properties allowed by react-select |
CheckBoxList | layout |
RadioButtonList | layout |
DateTime | All properties allowed by react-datetime-picker |
Slider | min, max, step, isRange |
If your only concern is that the field is not empty you don't need to add a validation property to your field. Simply add a mandatoryMessage and your field will be deemed invalid if empty.
If your validation is more complex then you will need to add a more complicated property:
interface Validation {
accessors?: string[];
validate: (
currentField: FormField,
...dependantFields: FormField[]
) => boolean;
errorMessage: string;
}
gotta-go-form's validation allows for validation of varying complications.
Sometimes your validation might be dependant on the values of other fields. If that is the case put the accessors of the dependant fields here.
The function used to validate your field. The entire field obejct will always be passed as the first parameter to this function. All dependant fields specified in the accessors property will be passed in as supplementary parameters. These supplementary fields will be passed in the order specified in accessors
The message you want to display below the field if the user submits the form while this field is invalid
Sometimes you want fields to hidden in certain circumstances. You can define this with the visibility property
interface Visibility {
accessors: string[];
condition: (...dependantValues: any[]) => boolean;
}
the accessors of the fields that the current field needs to know the value of to determine whether it should be visible or not
A function that returns a boolean based on the values of the dependant fields The passed in values will be passed in the order specified in accessors
Sometimes you want the state of certain fields to be updated upon the change of other fields.
For example you might want an end time field that immediately sets itself to 15 minutes after the user has set a start time.
You can add this logic to your form using the observer property.
interface Observer {
observables: string[];
observerFunction: (
observer: FormField,
...Observables: FormField[]
) => FormField;
}
Adding this property turns your field into an observer who is watching for when other fields change
The accessors of the fields you want this field to observe.
This function will be called if the value of any of the observed fields change. The current (observer) field will be passed in as the first parameter and all observables will be passed in as supplementary parameters.
This function should update and return the observer field.
You'll likely want some global actions to take on your form. You do this by defining footer actions. Each of these actions will become a button in the footer of this form.
interface FooterAction {
text: string; //the test displayed on the button
disabled?: boolean;
type: 'Primary' | 'Secondary';
validate?: boolean;
onClick: (result: any) => void;
}
If you want to form to to be validated before it takes the action specified in the onClick function simply set the validate property to true. If the form is invalid then the error messages will be updated and the onClick function will not be called.
All onClick functions will be passed an object containing all the values of the form. For example, if you have a form with two inputs whose accessors are 'username' and 'password' respectively, you should expect an object like this:
{
username: 'jacob-pecile'
password: 'nicetryguy'
}
Right now gotta-go-form has enough for you to start creating forms, but there are more features planned, includeing:
- managing validation for only "dirty" fields
Datetime component built using : react-datetime-picker
Dropdown component built using : react-select