Form 表单

示例

表单-水平布局

<script lang="ts">
  let loginForm: Form
  let loginData = $state({ username: '', password: '' })

  // 自定义 required
  function usrRule(username: string) {
    if (!username?.length) return '请输入用户名'
  }

  // 密码复杂度验证
  function pwdRule(pwd: string) {
    return (
      /^(?=.*[a-zA-Z])(?=.*\d)[\w!@#$%^&*()-+=]{8,}$/.test(pwd) ||
      '8位以上英文+数字'
    )
  }

  // 表单提交
  async function handleSubmit(form: Form) {
    const valid = await form.validate()

    if (valid) {
      showToast({ text: '登录' })
    } else {
      showToast({ text: '内容有误' })
    }
  }
</script>

<Form
  bind:this={loginForm}
  bind:data={loginData}
  header="表单-水平布局"
  layout="horizontal"
  --sunp-label-width="80px"
>
  <FormItem label="用户名" field="username" required={usrRule}>
    <Input
      bind:value={loginData.username}
      placeholder="请输入用户名"
      autocomplete="username"
    />
  </FormItem>
  <FormItem label="密码" field="password" required rules={[pwdRule]}>
    <Input
      type="password"
      bind:value={loginData.password}
      placeholder="请输入密码"
      autocomplete="current-password"
    />
  </FormItem>
</Form>

<div class="bg-white px-4 py-2">
  <Space>
    <Button color="primary" onclick={() => handleSubmit(loginForm)}>提交</Button
    >
    <Button
      color="normal"
      onclick={() => loginForm.reset({ username: '', password: '' })}
      >重置</Button
    >
  </Space>
</div>

表单-垂直布局-默认

<script lang="ts">
  let loginForm2: Form
  let loginData2 = $state<[username?: string, password?: string]>(['', ''])
</script>

<Form bind:this={loginForm2} bind:data={loginData2} header="表单-垂直布局-默认">
  <FormItem label="用户名" field={0} required={usrRule}>
    <Input
      bind:value={loginData2[0]}
      placeholder="请输入用户名"
      autocomplete="username"
    />
  </FormItem>
  <FormItem label="密码" field={1} required rules={[pwdRule]}>
    <Input
      type="password"
      bind:value={loginData2[1]}
      placeholder="请输入密码"
      autocomplete="current-password"
    />
  </FormItem>
</Form>

<div class="bg-white px-4 py-2">
  <Space>
    <Button color="primary" onclick={() => handleSubmit(loginForm2)}
      >提交</Button
    >
    <Button color="normal" onclick={() => loginForm2.reset(['', ''])}
      >重置</Button
    >
  </Space>
</div>

表单-可点击项

<Form header="表单-可点击项" layout="horizontal">
  <FormItem
    label="点我试试"
    clickable
    onClick={() => showToast({ text: 'Hello' })}
  >
    <div class="w-full">试试就试试</div>
  </FormItem>
</Form>

表单-混合布局

<Form header="表单-混合布局" layout="horizontal">
  <FormItem label="文本-水平">
    <Input placeholder="请填写文本" />
  </FormItem>
  <FormItem label="备注-垂直" layout="vertical">
    <Textarea placeholder="请填写备注" />
  </FormItem>
  <FormItem label="步进器-水平">
    <Stepper />
  </FormItem>
  <FormItem label="步进器-垂直" layout="vertical">
    <Stepper />
  </FormItem>
  <FormItem label="开关-水平">
    <Switch />
  </FormItem>
  <FormItem label="开关-垂直" layout="vertical">
    <Switch />
  </FormItem>
</Form>

Form

属性

属性 说明 类型 默认值
header 标题 string | Snippet undefined
layout 布局模式 'horizontal' | 'vertical' 'vertical'
data 表单对象 Record undefined

方法

方法 说明 类型
validate 表单验证 (异步) () => Promise
reset 表单数据重置,并清除验证错误 (data: Record) => void

FormHeader

Form 的子元素,通常作为 Form 的子标题或者间隔使用。

FormItem

属性

属性 说明 类型 默认值
label 标签名 string | Snippet undefined
layout 布局模式 'horizontal' | 'vertical' 'vertical'
field 提供表单条目对应的字段 PropertyKey undefined
required 是否必填/自定义错误信息/自定义校验逻辑 boolean | string | [Rule](#rule-type) false
rules 自定义校验逻辑 Array<[Rule](#rule-type)> undefined
error 表单条目错误信息 string $bindable()
clickable 是否可以点击。'auto' 表示由 FormItem 的子组件控制 boolean | 'auto' 'auto'

事件

事件 说明 类型
onClick FormItem 点击事件。clickable === false 时不会触发此事件 () => void
onclick HTML 原生的点击事件。注意与 onClick 的区别 (e: MouseEvent) => void

表单验证

必须为 Form 提供 data 属性。必须为 FormItem 提供 field 属性。

FormItem 提供了 requiredrules 这两个校验项。校验函数会优先校验 required 逻辑,然后按数组顺序校验 rules。

Required

当 required 有值时,会显示 * 星号。

以下 value 不能通过 required 校验:

  • null | undefined
  • 空字符串/空白
  • 空数组
  • 无效的数字
  • 无效的日期

Rule

/**
 * 自定义表单条目的校验逻辑
 * @val 当前表单的值
 * @return 如果返回值的类型为 string,且截断前后空白后字符串长度 > 0,则表示未通过验证
 */
type Rule = (val: any) => any | PromiseLike<any>

CSS 变量

属性 说明 默认值
--sunp-label-width 标签宽度。表单布局为 'horizontal' 时有效 102px

FormArray

TODO