Form Builder
Metafox includes the most popular React Form library formik
and validation with yup
, wraps theme in FormBuilder
in order to help build, configure flexible logic from AdminCP without modifying source code.
The Form mechanism on MetaFox is based on formik
+ material-ui
. It can build a Form with certain fields & structure with JSON schema. Let's take a look at the below example.
Schema
import { Form } from "@metafox/form";
const ExampleLoginForm = () => {
const loginFormSchema = {
{
"component": "Form",
"method": "POST",
"title": "Login",
"noBreadcrumb": true,
"submitAction": "@login",
"action": "/user/login",
"acceptPageParams": [
"returnUrl"
],
"value": [],
"validation": {
"type": "object",
"properties": {
"email": {
"type": "string",
"errors": {
"required": "[${path} is a required field.]"
},
"required": true,
"label": "[Username, email or phone number]"
},
"password": {
"type": "string",
"errors": {
"required": "[${path} is a required field.]"
},
"required": true,
"label": "[Password]"
}
}
},
"elements": {
"basic": {
"component": "Container",
"name": "basic",
"testid": "field basic",
"elements": {
"email": {
"name": "email",
"maxLength": 255,
"fullWidth": true,
"variant": "outlined",
"margin": "normal",
"size": "medium",
"component": "Text",
"label": "[Username, email or phone number]",
"required": true,
"inputLabelProps": {
"shrink": true
},
"placeholder": "[Enter your username, email or phone number]",
"autoComplete": "email",
"autoFocus": true,
"testid": "field email"
},
"password": {
"component": "Password",
"name": "password",
"type": "password",
"autoComplete": "password",
"maxLength": 255,
"fullWidth": true,
"variant": "outlined",
"label": "[Password]",
"required": true,
"margin": "normal",
"inputLabelProps": {
"shrink": true
},
"placeholder": "[Enter your password]",
"testid": "field password"
},
"remember": {
"component": "Checkbox",
"checkedValue": true,
"uncheckedValue": 0,
"fullWidth": true,
"margin": "dense",
"name": "remember",
"label": "[Remember Me]",
"testid": "field remember"
},
"login": {
"component": "Submit",
"name": "login",
"size": "large",
"variant": "contained",
"label": "[Sign In]",
"type": "submit",
"color": "primary",
"margin": "normal",
"fullWidth": true,
"testid": "field login"
},
"forgotPassword": {
"component": "LinkButton",
"color": "primary",
"variant": "link",
"size": "medium",
"fullWidth": true,
"name": "forgotPassword",
"link": "/user/password/request",
"margin": "none",
"label": "[Forgot Password?]",
"testid": "field forgotPassword"
},
"register": {
"component": "LinkButton",
"color": "primary",
"variant": "outlined",
"size": "large",
"fullWidth": true,
"name": "register",
"link": "/register",
"margin": "dense",
"label": "[Don't have an account?]",
"sx": {
"pt": 3
},
"testid": "field register"
},
"returnUrl": {
"component": "Hidden",
"name": "returnUrl",
"testid": "field returnUrl"
}
}
}
}
}
};
const initialValues = {
email: "[email protected]",
password: "",
};
return <Form schema={loginFormSchema} initialValues={initialValues} />;
};
Elements
Here is the list of Supported Form elements
Text
Definition
export type TextFieldProps = {
name: string;
component: "Text";
label: string;
placeholder: string;
readOnly?: boolean;
disabled?: boolean;
required?: boolean;
maxLength?: number;
variant?: "outlined" | "filled";
type?: "text" | "email" | "password" | "number" | "date" | "time";
};
Blow is the example to create a Text element
const Field = {
name: "title",
component: "Text",
label: "Title",
placeholder: "Enter an title for this blog",
readOnly: false, // optional
disabled: false, // optional
required: false, // optional
maxLength: 250, // optional
autoComplete: true, //optional,
variant: "outlined",
};
Switch
Definition:
export type SwitchFieldProps = {
name: string;
component: "Switch";
label: string;
placeholder: string;
readOnly?: boolean;
disabled?: boolean;
required?: boolean;
maxLength?: number;
variant?: "outlined" | "filled";
type?: "text" | "email" | "password" | "number" | "date" | "time";
label: string;
margin: "dense" | "none" | "normal";
labelPlacement?: "bottom" | "end" | "start" | "top";
checkedValue?: any;
uncheckedValue?: any;
size: "medium" | "small" | string;
color:
| "default"
| "primary"
| "secondary"
| "error"
| "info"
| "success"
| "warning"
| string;
fullWidth: boolean;
warning?: string;
description?: string;
variant: "filled" | "outlined" | "standard";
};
Example:
const Field = {
component: "Switch",
fullWidth: true,
margin: "normal",
color: "primary",
labelPlacement: "start",
name: "is_wiki",
label: "Label here ...",
description: "Description here ...",
testid: "field toggle",
};
Checkbox
Definition:
export type SwitchFieldProps = {
name: string;
component: "Checkbox";
variant: "filled" | "outlined" | "standard";
label: string;
disabled?: boolean;
checkedValue?: any;
uncheckedValue?: any;
margin: "dense" | "none" | "normal";
size: "medium" | "small" | string;
fullWidth: boolean;
color:
| "default"
| "primary"
| "secondary"
| "error"
| "info"
| "success"
| "warning"
| string;
description?: string;
required?: boolean;
sxFieldWrapper?: sxMui;
};
Example:
const Field = {
component: "Checkbox",
checkedValue: 1,
uncheckedValue: 0,
fullWidth: true,
margin: "dense",
name: "is_active",
multiple: false,
label: "Label here ...",
disabled: false,
testid: "field is_active",
};
RadioGroup
Definition:
export type SwitchFieldProps = {
name: string;
component: "RadioGroup";
variant: "filled" | "outlined" | "standard";
label: string;
disabled?: boolean;
margin: "dense" | "none" | "normal";
size: "medium" | "small" | string;
fullWidth: boolean;
description?: string;
required?: boolean;
};
Example:
const Field = {
component: "RadioGroup",
options: [
{
label: "Option 1",
value: 1,
},
{
label: "Option 2",
value: 2,
},
],
fullWidth: true,
name: "field_radio",
label: "Label",
description: "Description here ...",
required: false,
descriptionPlacement: "bottom",
testid: "field field_radio",
};
Select
Definition:
export type SwitchFieldProps = {
name: string;
component: "RadioGroup";
variant: "filled" | "outlined" | "standard";
label: string;
disabled?: boolean;
margin: "dense" | "none" | "normal";
size: "medium" | "small" | string;
fullWidth: boolean;
description?: string;
required?: boolean;
sxFieldWrapper?: sxMui;
options: Array[];
};
Example:
const Field = {
component: "Select",
fullWidth: true,
name: "field_select",
label: "selection",
description: "Description here ...",
required: false,
options: [
{
label: "Option 1",
value: 1,
},
{
label: "Option 2",
value: 2,
},
],
testid: "field field_select",
};
Datetime
Definition:
export type SwitchFieldProps = {
name: string;
component: "Datetime";
variant: "filled" | "outlined" | "standard";
label: string;
disabled?: boolean;
margin: "dense" | "none" | "normal";
size: "medium" | "small" | string;
fullWidth: boolean;
description?: string;
required?: boolean;
displayFormat: string;
timeFormat: 12 | 24;
timeSuggestion: boolean;
labelTimePicker: string;
labelDatePicker: string;
};
Example:
const Field = {
component: "Datetime",
variant: "outlined",
name: "start_time",
required: true,
disabled: false,
displayFormat: "DD/MM/YYYY - HH:mm",
timeFormat: 24,
timeSuggestion: true,
labelTimePicker: "Start Time",
labelDatePicker: "Start Date",
testid: "field start_time",
};
Tags
Definition:
export type SwitchFieldProps = {
name: string;
component: "Tags";
variant: "filled" | "outlined" | "standard";
label: string;
disabled?: boolean;
margin: "dense" | "none" | "normal";
size: "medium" | "small" | string;
fullWidth: boolean;
description?: string;
required?: boolean;
search_endpoint: string;
placeholder?: string;
};
Example:
const Field = {
component: "Tags",
maxLength: 255,
name: "tags",
fullWidth: true,
margin: "normal",
variant: "outlined",
search_endpoint: "/hashtag/suggestion",
description: "Separate multiple topics by entering.",
label: "Topics",
placeholder: "Keywords",
testid: "field tags",
};
PrivacySelect
Definition:
export type SwitchFieldProps = {
name: string;
component: "Privacy";
variant: "filled" | "outlined" | "standard";
label: string;
disabled?: boolean;
margin: "dense" | "none" | "normal";
fullWidth: boolean;
description?: string;
required?: boolean;
options: Array[];
};
Example:
const Field = {
"component": "Privacy",
"label": "Privacy",
"name": "privacy",
"fullWidth": true,
"variant": "outlined",
"options": [
{
"label": "Everyone",
"value": 0
},
{
"label": "Community",
"value": 1
},
{
"label": "Friends",
"value": 2
},
{
"label": "Friends of Friends",
"value": 3
},
{
"label": "Only Me",
"value": 4
},
{
"label": "Custom",
"value": 10
}
],
"description": "Control who can see this blog.",
"testid": "field privacy"
};
ButtonSubmit
Definition:
export type SwitchFieldProps = {
name: string;
component: "Submit";
type: 'button';
disabled: boolean;
color:
| "default"
| "primary"
| "secondary"
| "error"
| "info"
| "success"
| "warning"
| string;
margin: "dense" | "none" | "normal";
label: string;
size: "large" | "medium" | "small" | string;
fullWidth: boolean;
variant: "outlined" | "contained" | "text"
};
Example:
const Field = {
"component": "Submit",
"name": "submit",
"size": "large",
"variant": "contained",
"label": "Update",
"type": "submit",
"color": "primary",
"testid": "field submit"
};
Button
Definition:
export type SwitchFieldProps = {
name: string;
component: "Button";
type: 'button';
disabled: boolean;
color:
| "default"
| "primary"
| "secondary"
| "error"
| "info"
| "success"
| "warning"
| string;
margin: "dense" | "none" | "normal";
label: string;
size: "large" | "medium" | "small" | string;
fullWidth: boolean;
variant: "outlined" | "contained" | "text"
};
Example:
const Field = {
"component": "Button",
"name": "action",
"size": "large",
"variant": "contained",
"label": "Update",
"type": "button",
"color": "primary",
"testid": "field action"
};
Container
Definition:
export type SwitchFieldProps = {
name: string;
component: "Container";
elements: Record<string, FormElementShape>;
collapsible?: boolean;
variant: "vertical" | "horizontal";
label: string;
wrapperProps?: Record<string, any>;
};
Example:
const Field = {
"component": "Container",
"name": "customsection",
"label": "Container",
"description": null,
"testid": "field customsection",
"elements": {
// config elements
}
}
Note: During Metafox upgrade, config may be unwanted change that this document can be outdated. Please refer to the source code during develop to update the latest fields config.