Skip to main content

Form

Used for collecting, validating, and submitting form data.

When to Use

  • Need to create a data entry form
  • Need to validate user input
  • Need to submit data
  • Need to dynamically add/remove form fields

Examples

Basic Usage

The simplest usage, getting form data via onFinish.

Live Editor
function Demo() {
  const handleFinish = (values) => {
    console.log('Form data:', values);
    alert(JSON.stringify(values, null, 2));
  };

  return (
    <Form onFinish={handleFinish}>
      <FormItem
        name="username"
        label="Username"
        rules={[{ required: true, message: 'Please enter username' }]}
      >
        <Input placeholder="Please enter username" />
      </FormItem>
      <FormItem
        name="email"
        label="Email"
        rules={[
          { required: true, message: 'Please enter email' },
          { type: 'email', message: 'Please enter a valid email address' },
        ]}
      >
        <Input placeholder="Please enter email" />
      </FormItem>
      <FormItem>
        <Button type="submit" variant="filled" color="primary">
          Submit
        </Button>
      </FormItem>
    </Form>
  );
}
Result
Loading...

Form Layout

Set form layout using the layout prop.

Live Editor
function Demo() {
  const [layout, setLayout] = React.useState('vertical');

  return (
    <div>
      <Group style={{ marginBottom: '24px' }}>
        <Button onClick={() => setLayout('horizontal')}>Horizontal</Button>
        <Button onClick={() => setLayout('vertical')}>Vertical</Button>
        <Button onClick={() => setLayout('inline')}>Inline</Button>
      </Group>

      <Form layout={layout} onFinish={(values) => console.log(values)}>
        <FormItem name="name" label="Name" rules={[{ required: true }]}>
          <Input />
        </FormItem>
        <FormItem name="age" label="Age">
          <Input />
        </FormItem>
        <FormItem>
          <Button type="submit">Submit</Button>
        </FormItem>
      </Form>
    </div>
  );
}
Result
Loading...

Form Validation

Supports multiple validation rules.

Live Editor
function Demo() {
  const handleFinish = (values) => {
    alert('Validation passed: ' + JSON.stringify(values));
  };

  return (
    <Form onFinish={handleFinish}>
      <FormItem
        name="username"
        label="Username"
        rules={[
          { required: true, message: 'Username is required' },
          { min: 3, message: 'Username must be at least 3 characters' },
          { max: 20, message: 'Username must be at most 20 characters' },
        ]}
      >
        <Input />
      </FormItem>
      <FormItem
        name="password"
        label="Password"
        rules={[
          { required: true, message: 'Password is required' },
          { min: 6, message: 'Password must be at least 6 characters' },
        ]}
      >
        <InputPassword />
      </FormItem>
      <FormItem
        name="confirm"
        label="Confirm Password"
        dependencies={['password']}
        rules={[
          { required: true, message: 'Please confirm password' },
          ({ getFieldValue }) => ({
            validator(_, value) {
              if (!value || getFieldValue('password') === value) {
                return Promise.resolve();
              }
              return Promise.reject(new Error('Passwords do not match'));
            },
          }),
        ]}
      >
        <InputPassword />
      </FormItem>
      <FormItem>
        <Button type="submit" variant="filled" color="primary">
          Submit
        </Button>
      </FormItem>
    </Form>
  );
}
Result
Loading...

Dynamic Form Items

Use FormList to implement dynamic add/remove form items.

Live Editor
function Demo() {
  const { Add, Trash } = KubedIcons;

  return (
    <Form onFinish={(values) => console.log(values)}>
      <FormList name="users">
        {(fields, { add, remove }) => (
          <>
            {fields.map(({ key, name, ...restField }) => (
              <Group key={key} style={{ marginBottom: '12px' }}>
                <FormItem
                  {...restField}
                  name={[name, 'firstName']}
                  label="First Name"
                  rules={[{ required: true, message: 'Please enter first name' }]}
                  style={{ marginBottom: 0, flex: 1 }}
                >
                  <Input />
                </FormItem>
                <FormItem
                  {...restField}
                  name={[name, 'lastName']}
                  label="Last Name"
                  rules={[{ required: true, message: 'Please enter last name' }]}
                  style={{ marginBottom: 0, flex: 1 }}
                >
                  <Input />
                </FormItem>
                <Button variant="text" color="error" onClick={() => remove(name)}>
                  <Trash size={16} />
                </Button>
              </Group>
            ))}
            <Button onClick={() => add()} leftIcon={<Add size={16} />}>
              Add User
            </Button>
          </>
        )}
      </FormList>
      <FormItem style={{ marginTop: '24px' }}>
        <Button type="submit" variant="filled" color="primary">
          Submit
        </Button>
      </FormItem>
    </Form>
  );
}
Result
Loading...

Form Methods

Use the useForm Hook to get a form instance and call form methods.

Live Editor
function Demo() {
  const [form] = useForm();

  const handleFill = () => {
    form.setFieldsValue({
      username: 'admin',
      email: 'admin@example.com',
    });
  };

  const handleReset = () => {
    form.resetFields();
  };

  const handleGetValues = () => {
    const values = form.getFieldsValue();
    alert(JSON.stringify(values, null, 2));
  };

  return (
    <div>
      <Group style={{ marginBottom: '16px' }}>
        <Button onClick={handleFill}>Fill Data</Button>
        <Button onClick={handleReset}>Reset</Button>
        <Button onClick={handleGetValues}>Get Values</Button>
      </Group>
      <Form form={form} onFinish={(values) => console.log(values)}>
        <FormItem name="username" label="Username" rules={[{ required: true }]}>
          <Input />
        </FormItem>
        <FormItem name="email" label="Email" rules={[{ required: true, type: 'email' }]}>
          <Input />
        </FormItem>
        <FormItem>
          <Button type="submit" variant="filled" color="primary">
            Submit
          </Button>
        </FormItem>
      </Form>
    </div>
  );
}
Result
Loading...

Checkbox Group

Using CheckboxGroup in forms.

Live Editor
function Demo() {
  return (
    <Form onFinish={(values) => alert(JSON.stringify(values, null, 2))}>
      <FormItem name="permissions" label="Permissions" rules={[{ required: true, message: 'Please select permissions' }]}>
        <CheckboxGroup>
          <Checkbox label="Read" value="read" />
          <Checkbox label="Write" value="write" />
          <Checkbox label="Delete" value="delete" />
          <Checkbox label="Execute" value="execute" />
        </CheckboxGroup>
      </FormItem>
      <FormItem>
        <Button type="submit" variant="filled" color="primary">
          Submit
        </Button>
      </FormItem>
    </Form>
  );
}
Result
Loading...

Grid Layout

Using Grid component for complex form layouts.

Live Editor
function Demo() {
  return (
    <Form onFinish={(values) => console.log(values)}>
      <Row gutter={[16, 16]}>
        <Col span={12}>
          <FormItem name="firstName" label="First Name" rules={[{ required: true }]}>
            <Input />
          </FormItem>
        </Col>
        <Col span={12}>
          <FormItem name="lastName" label="Last Name" rules={[{ required: true }]}>
            <Input />
          </FormItem>
        </Col>
        <Col span={12}>
          <FormItem name="email" label="Email" rules={[{ required: true, type: 'email' }]}>
            <Input />
          </FormItem>
        </Col>
        <Col span={12}>
          <FormItem name="phone" label="Phone" rules={[{ required: true }]}>
            <Input />
          </FormItem>
        </Col>
        <Col span={24}>
          <FormItem name="address" label="Address">
            <Textarea />
          </FormItem>
        </Col>
      </Row>
      <FormItem>
        <Button type="submit" variant="filled" color="primary">
          Submit
        </Button>
      </FormItem>
    </Form>
  );
}
Result
Loading...

Help Text and Tooltip

Add additional information using help and tooltip props.

Live Editor
function Demo() {
  const { Question } = KubedIcons;

  return (
    <Form onFinish={(values) => console.log(values)}>
      <FormItem
        name="username"
        label="Username"
        help="Username is used to log in to the system"
        rules={[{ required: true }]}
      >
        <Input />
      </FormItem>
      <FormItem
        name="apiKey"
        label="API Key"
        tooltip="API key is used for API authentication, please keep it secure"
        rules={[{ required: true }]}
      >
        <Input />
      </FormItem>
      <FormItem>
        <Button type="submit" variant="filled" color="primary">
          Submit
        </Button>
      </FormItem>
    </Form>
  );
}
Result
Loading...

API

Form Props

PropertyDescriptionTypeDefault
formForm instance, created by useFormFormInstance-
nameForm namestring-
layoutForm layout'horizontal' | 'vertical' | 'inline''vertical'
labelAlignLabel alignment'left' | 'right''right'
labelColLabel grid layoutColProps{span: 4}
wrapperColInput control grid layoutColProps{span: 14}
sizeForm component sizeKubedSizes'sm'
initialValuesForm initial valuesobject-
onFinishCallback when form submit passes validation(values: any) => void-
onFinishFailedCallback when form submit fails validation(errorInfo: ValidateErrorEntity) => void-
onValuesChangeCallback when field value updates(changedValues, allValues) => void-
validateMessagesValidation message templatesValidateMessages-
scrollToFirstErrorAuto scroll to first error field on submit failureboolean | Optionsfalse
othersNative attributesHTMLAttributes<HTMLFormElement>-
info

About Form Layout:

  • horizontal: Horizontal layout, label and control on same line
  • vertical: Vertical layout, label and control stacked vertically (default)
  • inline: Inline layout, all form items on one line

About Form Instance:

  • Use useForm() Hook to create form instance
  • Form instance provides rich methods to manipulate the form

FormItem Props

PropertyDescriptionTypeDefault
nameField namestring | string[]-
labelLabel textReactNode-
rulesValidation rulesRule[]-
requiredWhether field is requiredbooleanfalse
helpHelp textReactNode-
tooltipTooltip (shown on hover)ReactNode-
dependenciesDependent fieldsstring[]-
valuePropNameValue property name of child nodestring'value'
initialValueInitial valueany-
othersNative attributesHTMLAttributes<HTMLElement>-
info

About Validation Rules:

  • required: Whether field is required
  • type: Field type (string, number, email, url, etc.)
  • min / max: Minimum/maximum length or value
  • pattern: Regular expression
  • validator: Custom validation function
  • message: Error message

About dependencies:

  • When dependent fields update, current field validation is triggered
  • Commonly used for confirm password scenarios

FormList

Used to render dynamic form item lists.

<FormList name="users">
{(fields, { add, remove }) => (
<>
{fields.map((field) => (
<FormItem key={field.key} {...field}>
<Input />
</FormItem>
))}
<Button onClick={() => add()}>Add</Button>
</>
)}
</FormList>

Form Instance Methods

MethodDescriptionType
getFieldValueGet value of specific field(name: string) => any
getFieldsValueGet values of all fields() => any
setFieldValueSet value of specific field(name: string, value: any) => void
setFieldsValueSet values of multiple fields(values: any) => void
resetFieldsReset form(fields?: string[]) => void
validateFieldsTrigger form validation(nameList?: string[]) => Promise<any>
submitSubmit form() => void
scrollToFieldScroll to specific field(name: string, options?: Options) => void

Usage Guidelines

Form Validation

Common validation rule examples:

// Required
{ required: true, message: 'This field is required' }

// Email
{ type: 'email', message: 'Please enter a valid email address' }

// Length limit
{ min: 3, max: 20, message: 'Length must be between 3 and 20 characters' }

// Regular expression
{ pattern: /^1[3-9]\d{9}$/, message: 'Please enter a valid phone number' }

// Custom validation
{
validator: (_, value) => {
if (value && value < 18) {
return Promise.reject('Age must be greater than 18');
}
return Promise.resolve();
}
}

Dynamic Forms

Implementing dynamic forms with FormList:

<FormList name="members">
{(fields, { add, remove }) => (
<>
{fields.map((field, index) => (
<Row key={field.key}>
<Col span={10}>
<FormItem {...field} name={[field.name, 'name']}>
<Input />
</FormItem>
</Col>
<Col span={10}>
<FormItem {...field} name={[field.name, 'age']}>
<Input />
</FormItem>
</Col>
<Col span={4}>
<Button onClick={() => remove(field.name)}>Delete</Button>
</Col>
</Row>
))}
<Button onClick={() => add()}>Add Member</Button>
</>
)}
</FormList>

Form Linkage

Implementing form linkage via dependencies and custom validation:

<FormItem name="country" label="Country">
<Select />
</FormItem>

<FormItem
name="province"
label="Province"
dependencies={['country']}
rules={[
({ getFieldValue }) => ({
validator(_, value) {
const country = getFieldValue('country');
if (country === 'China' && !value) {
return Promise.reject('Please select province');
}
return Promise.resolve();
},
}),
]}
>
<Select />
</FormItem>