Skip to content

Form

表单组件族,与 @tanstack/react-form 完全集成,提供类型安全的表单字段组件。

导入

tsx
import { Form } from '@xcloud/ui-core'
import { useForm } from '@tanstack/react-form'

示例

基础用法

tsx
import { useForm } from '@tanstack/react-form';
import { Form } from '@xcloud/ui-core';

interface LoginFormData {
  email: string;
  password: string;
  remember: boolean;
}

export function LoginForm() {
  const form = useForm<LoginFormData>({
    defaultValues: {
      email: '',
      password: '',
      remember: false,
    },
    onSubmit: async ({ value }) => {
      console.log(value);
    },
  });

  return (
    <form onSubmit={(e) => { e.preventDefault(); form.handleSubmit(); }}>
      <Form.FormField.Root<LoginFormData>
        form={form}
        name="email"
        label="邮箱地址"
        type="email"
        required
      />

      <Form.FormField.Root<LoginFormData>
        form={form}
        name="password"
        label="密码"
        type="password"
        required
      />

      <Form.FormSwitchField.Root<LoginFormData>
        form={form}
        name="remember"
        label="记住我"
      />

      <button type="submit">登录</button>
    </form>
  );
}

可用组件

FormField

文本输入字段

tsx
<Form.FormField.Root<TFormData>
  form={form}
  name="fieldName"
  label="标签"
  hint="提示信息"
  type="text"
  placeholder="占位符"
  icon={IconComponent}
  required
  disabled
/>

FormTextareaField

多行文本输入

tsx
<Form.FormTextareaField.Root<TFormData>
  form={form}
  name="fieldName"
  label="标签"
  rows={4}
  maxLength={200}
/>

FormSelectField

下拉选择框

tsx
<Form.FormSelectField.Root<TFormData>
  form={form}
  name="fieldName"
  label="选择一个选项"
  placeholder="请选择"
  options={[
    { value: 'option1', label: '选项 1' },
    { value: 'option2', label: '选项 2', disabled: true },
  ]}
/>

FormRadioField

单选按钮组

tsx
<Form.FormRadioField.Root<TFormData>
  form={form}
  name="fieldName"
  label="选择一个选项"
  options={[
    { value: 'option1', label: '选项 1' },
    { value: 'option2', label: '选项 2' },
  ]}
/>

FormCheckboxField

复选框

tsx
<Form.FormCheckboxField.Root<TFormData>
  form={form}
  name="fieldName"
  label="我同意服务条款"
/>

FormSwitchField

开关

tsx
<Form.FormSwitchField.Root<TFormData>
  form={form}
  name="fieldName"
  label="启用此选项"
  hint="开启后将..."
/>

FormSegmentedControlField

分段控制器

tsx
<Form.FormSegmentedControlField.Root<TFormData>
  form={form}
  name="fieldName"
  label="选择模式"
  options={[
    { value: 'light', label: '浅色' },
    { value: 'dark', label: '深色' },
    { value: 'auto', label: '自动' },
  ]}
/>

FormDigitField

验证码输入

tsx
<Form.FormDigitField.Root<TFormData>
  form={form}
  name="verificationCode"
  label="验证码"
  numInputs={6}
/>

FormCustomField

自定义字段渲染

tsx
<Form.FormCustomField.Root<TFormData>
  form={form}
  name="customField"
>
  {(field) => (
    <div>
      <label>自定义字段</label>
      <MyCustomInput
        value={field.state.value}
        onChange={(value) => field.handleChange(value)}
        onBlur={field.handleBlur}
      />
      {field.state.meta.errors.length > 0 && (
        <span className="text-red-500">
          {field.state.meta.errors[0]}
        </span>
      )}
    </div>
  )}
</Form.FormCustomField.Root>

类型安全

所有 Form 组件都支持泛型类型参数,提供完整的类型提示:

tsx
// ✅ 字段名自动完成
<Form.FormField.Root<LoginFormData>
  form={form}
  name="email"  // TypeScript 会提示: "email" | "password" | "remember"
/>

// ❌ TypeScript 会报错
<Form.FormField.Root<LoginFormData>
  form={form}
  name="username"  // 错误:'username' 不存在于 LoginFormData
/>

Field API

FormCustomField 中,field 对象提供以下属性和方法:

  • field.state.value - 当前字段值
  • field.state.meta.errors - 验证错误数组
  • field.state.meta.isTouched - 字段是否被触摸过
  • field.state.meta.isDirty - 字段值是否被修改过
  • field.handleChange(value) - 更新字段值
  • field.handleBlur() - 处理失焦事件

更多 API 请参考 @tanstack/react-form 文档

最佳实践

  1. 总是定义表单数据类型
tsx
// ✅ 好
interface MyFormData { ... }
const form = useForm<MyFormData>({ ... });

// ❌ 不好
const form = useForm({ ... }); // 失去类型安全
  1. 使用泛型指定表单类型
tsx
// ✅ 好 - 获得字段名自动完成
<Form.FormField.Root<MyFormData> form={form} name="..." />

// ⚠️ 可以工作,但失去自动完成
<Form.FormField.Root form={form} name="..." />
  1. 结合验证库使用
tsx
import { zodValidator } from '@tanstack/zod-form-adapter';
import { z } from 'zod';

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
});

const form = useForm({
  validatorAdapter: zodValidator,
  validators: {
    onChange: schema,
  },
});

相关资源

基于 MIT 许可发布