6.4 KiB
6.4 KiB
Schema Form
Introduction
A React component capable of building HTML forms out of a JSON schema.
Usage
import React, { useState } from 'react';
import {
SchemaForm,
initFormData,
JSONSchema,
UISchema,
FormKit,
} from '@/components';
const schema: JSONSchema = {
title: 'General',
properties: {
name: {
type: 'string',
title: 'Name',
},
age: {
type: 'number',
title: 'Age',
},
sex: {
type: 'string',
title: 'sex',
enum: [1, 2],
enumNames: ['male', 'female'],
},
},
};
const uiSchema: UISchema = {
name: {
'ui:widget': 'input',
},
age: {
'ui:widget': 'input',
'ui:options': {
type: 'number',
},
},
sex: {
'ui:widget': 'radio',
},
};
const Form = () => {
const [formData, setFormData] = useState(initFormData(schema));
const formRef = useRef<{
validator: () => Promise<boolean>;
}>(null);
const refreshConfig: FormKit['refreshConfig'] = async () => {
// refreshFormConfig();
};
const handleChange = (data) => {
setFormData(data);
};
return (
<SchemaForm
ref={formRef}
schema={schema}
uiSchema={uiSchema}
formData={formData}
onChange={handleChange}
refreshConfig={refreshConfig}
/>
);
};
export default Form;
Form Props
interface FormProps {
// Describe the form structure with schema
schema: JSONSchema | null;
// Describe the properties of the field
uiSchema?: UISchema;
// Describe form data
formData: Type.FormDataType | null;
// Callback function when form data changes
onChange?: (data: Type.FormDataType) => void;
// Handler for when a form fires a `submit` event
onSubmit?: (e: React.FormEvent) => void;
/**
* Callback method for updating form configuration
* information (schema/uiSchema) in UIAction
*/
refreshConfig?: FormKit['refreshConfig'];
}
Form Ref
export interface FormRef {
validator: () => Promise<boolean>;
}
When you need to validate a form and get the result outside the form, you can create a FormRef with useRef and pass it to the form using the ref property.
This allows you to validate the form and get the result outside the form using formRef.current.validator().
Types Definition
JSONSchema
export interface JSONSchema {
title: string;
description?: string;
required?: string[];
properties: {
[key: string]: {
type: 'string' | 'boolean' | 'number';
title: string;
label?: string;
description?: string;
enum?: Array<string | boolean | number>;
enumNames?: string[];
default?: string | boolean | number;
};
};
}
UISchema
export interface UISchema {
[key: string]: {
'ui:widget'?: UIWidget;
'ui:options'?: UIOptions;
};
}
UIWidget
export type UIWidget =
| 'textarea'
| 'input'
| 'checkbox'
| 'radio'
| 'select'
| 'upload'
| 'timezone'
| 'switch'
| 'legend'
| 'button';
UIOptions
export type UIOptions =
| InputOptions
| SelectOptions
| UploadOptions
| SwitchOptions
| TimezoneOptions
| CheckboxOptions
| RadioOptions
| TextareaOptions
| ButtonOptions;
BaseUIOptions
export interface BaseUIOptions {
empty?: string;
// Will be appended to the className of the form component itself
className?: classnames.Argument;
class_name?: classnames.Argument;
// The className that will be attached to a form field container
field_class_name?: classnames.Argument;
// Make a form component render into simplified mode
readOnly?: boolean;
simplify?: boolean;
validator?: (
value,
formData?,
) => Promise<string | true | void> | true | string;
}
InputOptions
export interface InputOptions extends BaseUIOptions {
placeholder?: string;
inputType?:
| 'color'
| 'date'
| 'datetime-local'
| 'email'
| 'month'
| 'number'
| 'password'
| 'range'
| 'search'
| 'tel'
| 'text'
| 'time'
| 'url'
| 'week';
}
SelectOptions
export interface SelectOptions extends UIOptions {}
UploadOptions
export interface UploadOptions extends BaseUIOptions {
acceptType?: string;
imageType?: Type.UploadType;
}
SwitchOptions
export interface SwitchOptions extends BaseUIOptions {
label?: string;
}
TimezoneOptions
export interface TimezoneOptions extends UIOptions {
placeholder?: string;
}
CheckboxOptions
export interface CheckboxOptions extends UIOptions {}
RadioOptions
export interface RadioOptions extends UIOptions {}
TextareaOptions
export interface TextareaOptions extends UIOptions {
placeholder?: string;
rows?: number;
}
ButtonOptions
export interface ButtonOptions extends BaseUIOptions {
text: string;
icon?: string;
action?: UIAction;
variant?: ButtonProps['variant'];
size?: ButtonProps['size'];
}
UIAction
export interface UIAction {
url: string;
method?: 'get' | 'post' | 'put' | 'delete';
loading?: {
text: string;
state?: 'none' | 'pending' | 'completed';
};
on_complete?: {
toast_return_message?: boolean;
refresh_form_config?: boolean;
};
}
FormKit
export interface FormKit {
refreshConfig(): void;
}
FormData
export interface FormValue<T = any> {
value: T;
isInvalid: boolean;
errorMsg: string;
[prop: string]: any;
}
export interface FormDataType {
[prop: string]: FormValue;
}
Backend API
For backend generating modal form you can return json like this.
Response
{
"name": "string",
"slug_name": "string",
"description": "string",
"version": "string",
"config_fields": [
{
"name": "string",
"type": "textarea",
"title": "string",
"description": "string",
"required": true,
"value": "string",
"ui_options": {
"placeholder": "placeholder",
"rows": 4
},
"options": [
{
"value": "string",
"label": "string"
}
]
}
]
}