Form

虽然你可以单独使用 FormKit 输入,但你通常会想要将它们组合成一个表单。要做到这一点,只需将你的输入包裹在一个 <FormKit type="form"> 中。

form 类型会主动收集所有子输入的值,使用每个输入的 name 作为结果数据对象中的属性名(就像 groups 一样)。你也可以使用 v-model 来读取和写入表单值,就像在任何输入上一样。

一个 <FormKit type="form"> 跟踪表单的验证状态,并防止用户在任何输入无效时提交表单。

提供的提交按钮

为了方便,form 自动输出一个提交 button,并且提供的主题也包括一个加载旋转器。你可以使用 submit-labelsubmit-attrs 属性来更改这个按钮,或者使用 :actions="false" 来禁用。你可以传递任何 FormKit 属性给 submit-attrs。在下面的示例中,我们传递了类、data 属性、帮助文本,甚至 告诉包含的提交按钮不被忽略

<FormKit
  type="form"
  submit-label="更新"
  :submit-attrs="{
    inputClass: 'my-input-class',
    wrapperClass: 'my-wrapper-class',
    'data-theme': `dark`,
    help: '我的按钮帮助文本',
    ignore: false
  }"
></FormKit>

完整示例表单

除了后端功能,这里是一个具有输入(formtextemailpassword)、帮助文本、标签、自定义消息的验证以及错误和提交处理的完整功能表单:

加载实时示例

填充

表单填充和提交 - Vue School 课程

8 分钟

你可以通过向 <FormKit type="form"> 提供一个 value 属性来填充整个表单。value 属性应该是输入名称到输入值对的对象。如果你需要双向数据绑定,你也可以使用 v-model 来填充表单:

加载实时示例
v-model 和响应式对象

请确保 v-model 一个 ref 或者一个 reactive 对象的属性。不要 v-model 响应式对象本身,因为它会 导致意外行为

提交

表单通常通过用户操作来提交,例如点击提交按钮或在表单内的文本节点上按下 enter 键。提交时,表单会按顺序:

  1. 确保所有输入都已完成(去抖动结束)。
  2. 触发 @submit-raw 事件。
  3. 将所有输入的 submitted 状态设置为 true — 显示任何剩余的验证错误(不管 validation-visibility 的设置)。
  4. 如果表单有验证错误,则触发 @submit-invalid 事件。
  5. 如果所有输入都有效,则触发 @submit 事件。
  6. 如果 @submit 处理器返回一个 Promise,则将表单的状态设置为 loading,直到它解决。
避免使用 v-model 收集和提交表单数据

在提交处理器中使用 v-model 数据可能会导致意外的表单变化。FormKit 自动 为您收集表单数据,因此请使用传递给您的提交处理器的未绑定副本的表单数据。

通过 XHR/Fetch 请求提交

在现代单页应用程序中,表单提交的最常见方法是 XHR 请求(想想 axiosfetch)。FormKit 非常适合这项任务:

  • 它将收集的表单数据作为一个请求就绪的对象(无需 v-model),以及 form 输入的核心节点,作为方便之用,交给您的 @submit 处理器。
  • 如果您使用异步提交处理器,它将禁用表单的输入并将加载状态应用到您的表单(context.state.loadingloading 变为 true,并且在 genesis 主题上显示旋转器)。
  • 它通过将错误消息直接放置在失败的输入上来处理后端错误
加载实时示例

作为页面请求提交

要通过页面请求提交表单,只需省略 @submit 处理器即可。就像原生 HTML 一样,您也可以提供一个 action,并且可以选择性地提供一个 method 属性。

加载实时示例

以编程方式提交表单

虽然使用任何标准 HTML 方法提交表单都是有效的(例如点击 submit 按钮,或在文本输入上按 enter)— 您也可以以编程方式提交表单。有两种方法可以做到这一点:

  • 使用 this.$formkit.submit('form-id')(对于组合 API 是 submitForm('form-id'))。
  • 使用核心节点对象。

使用 $formkit.submit() 提交

加载实时示例

使用 node.submit() 提交

你也可以通过在表单的(或表单内任何输入项的)核心节点上调用 node.submit() 来以编程方式提交表单。为此,你需要获取核心节点的实例

加载实时示例

禁用

要禁用给定表单中的所有输入项,包括提交按钮,你可以使用 disabled 属性。

加载实时示例
自动禁用

当使用异步的 @submit 处理器时,FormKit 会在提交处理器等待期间自动禁用表单(并将状态设置为 loading)。

重置

你可以通过调用 $formkit.reset(formId) 将你的表单(或任何输入项)重置回其初始状态。

加载实时示例
组合式 API

当使用组合式 API 时,你可以直接通过从核心导入 reset 函数来访问它:import { reset } from '@formkit/core'

初始值

需要注意的是,表单的“初始状态”并不一定是空表单。如果你在表单或表单中的个别输入项上有默认的 :valuev-model,FormKit 会自动将它们合并以产生你的初始值,并在重置时恢复到这个合并状态。

如果你更愿意有一个不同的重置状态,你可以选择性地提供第二个参数给 reset(formId, initialState)

验证

表单在表单中的所有输入项都通过其验证规则之前不会提交。

验证未完成消息

除了不触发提交事件外,还会在提交按钮上方显示一条消息,指示表单仍然不完整。你可以使用 incomplete-message 属性自定义此消息,或通过将属性设置为 false 来禁用它。

加载实时示例
全局自定义

如果你想在项目中更改所有表单的未完成消息,你可以修改 i18n 本地消息中的 ui.incomplete

提交无效事件

当用户尝试提交包含验证失败的输入的表单时,将触发 @submit-invalid 事件。

例如,我们可以使用这个事件来提醒用户验证规则失败。

加载实时示例

有效性状态

表单中所有输入的有效性都会在上下文对象中自动跟踪。这在创建各种界面时非常有用。例如,如果你希望提交按钮在所有输入都有效之前禁用,你可以使用 state.valid 属性来实现。

加载实时示例
获取上下文对象

在上面的示例中,我们从 #default 插槽中提取了上下文对象,但还有其他方法。上下文对象在每个输入的核心节点上都可通过 node.context 属性获得,你可以通过多种方式获取输入的节点。

错误处理

使用 FormKit,为你的表单添加前端验证很容易 — 但是后端框架产生的错误或你想手动分配的错误呢?你可以为表单分配两种类型的错误:

  • 表单错误。这些显示在表单底部的提交按钮上方。一个例子可能是像“对不起,我们的服务器现在无法工作”这样的全局消息。
  • 输入错误。要放置在表单内特定输入上的错误,通常是来自后端的验证错误,比如“对不起,这个用户名已经被占用”。

表单错误

表单错误(适用于整个表单的错误)可以通过三种方式设置。

  • <FormKit type="form"> 上使用 errors 属性。
  • 使用核心节点 node.setErrors()
  • 使用 $formkit.setErrors() Vue 插件方法。

使用 errors 属性

像任何 FormKit 输入一样,你可以直接使用 errors 属性分配错误。这些错误始终可见(不受 validation-visibility 影响)。

加载实时示例

使用 node.setErrors()

使用 node.setErrors 设置表单的错误很方便,因为你的提交处理程序会将表单的 node 对象作为其第二个参数传递。node.setErrors() 接受 2 个参数 — 一个用于表单错误的数组,和一个用于输入错误的键控对象:

加载实时示例

使用 $formkit.setErrors()

另外,你可以通过给表单一个 id,然后调用 $formkit.setErrors('id', ['表单错误信息']) 来直接在表单上设置错误。setErrors 方法必须传递表单的 id,然后可以处理 1 或 2 个额外的参数 — 表单错误和输入错误:

加载实时示例

清除错误

默认情况下,使用 setErrors() 设置在输入上的错误会在用户更改该输入的值时自动清除。你可以通过设置 preserve-errors 属性来更改这个默认行为。

要清除表单上的所有错误(不管 preserve-errors 属性如何),调用 node.clearErrors()

加载实时示例

如果你更愿意默认保留错误,你可以通过修改 preserveErrors 配置选项来更改默认行为。这可以全局完成,或者针对单个表单完成:

加载实时示例
Composition API

当使用 Vue 3 的 composition API 时,你可以直接从 @formkit/vue 导入 setErrorsclearErrors

import { setErrors, clearErrors } from '@formkit/vue'

输入错误

输入错误(要与表单中特定输入一起显示的错误)可以通过三种方式应用:

  • 在每个单独的输入上手动使用 errors 属性。
  • 在表单上使用 input-errors 属性(也适用于组和列表)。
  • 使用 $formkit.setErrors() Vue 插件方法(参见上面的示例)。

手动使用 errors 属性

在表单上显示错误的最基本方式是使用每个 FormKit 输入上可用的 errors 属性。

加载实时示例

使用 input-errors 属性

你还可以方便地使用 input-errors 属性为你的表单中的所有输入(或列表)设置错误消息。该属性接受一个错误对象,其中键是输入名称(支持相对节点地址),值是要应用于该输入的错误或错误数组。

加载实时示例

验证和错误摘要

为了提高可访问性,在表单顶部提供验证和错误信息的摘要是有帮助的。FormKit 提供了一个 <FormKitSummary /> 组件来为你渲染这个摘要。

这个组件会自动渲染表单所有的验证和错误信息,并带有跳转链接到它们所适用的输入框。这些错误只有在提交表单后才会显示,但它们被包裹在一个 aria-live 区域内以确保屏幕阅读器在错误出现时会被通知。此外,页面会自动滚动到摘要框并聚焦在第一个列出的错误上。

<FormKitSummary /> 不是一个全局注册的组件 — 你必须导入它:

import { FormKitSummary } from '@formkit/vue'
加载实时示例
移动摘要

摘要组件通常应嵌套在它正在总结的表单中。如果你想将摘要移动到页面的不同位置,你可以通过提供表单的核心节点作为 node 属性来实现。

移动验证和错误信息

默认情况下,表单的验证和错误信息被放置在表单操作部分的正上方。然而,你可以选择通过使用 <FormKitMessages /> 组件在页面的任何位置渲染这些信息。<FormKitMessages /> 不是一个全局注册的组件 — 你必须导入它:

import { FormKitMessages } from '@formkit/vue'

有两种使用 <FormKitMessages /> 的方法:

自动移动信息

在你的表单_内部_的任何位置放置一个 <FormKitMessages /> 组件,表单的信息将自动移动到那个位置:

加载实时示例

通过 node 移动信息

要将信息移动到 DOM 的任何位置 — 即使是_表单之外_ — 你可以将表单的核心节点作为属性传递给 <FormKitMessages />。在这个例子中,我们使用信息来创建一个吐司风格的弹出窗口:

加载实时示例

FormKitMessages 属性

<FormKitMessages /> 组件有一些额外的配置选项:

属性默认值描述
node继承要为其渲染信息的核心节点。默认情况下,这是从节点的父级继承的(如果存在的话)。
sectionsSchema{}覆盖内部的 messagesmessage 部分(与其他输入的消息部分相同的默认结构)。
defaultPositionfalse默认情况下,FormKitMessages 将渲染的信息移动到一个新位置。如果你希望在两个位置都渲染信息,请将此属性设置为 true

卸载输入项

当输入项从表单中卸载时 — 例如使用 v-if — 其键和值会从表单的数据中移除。然而,在某些情况下,即使输入项被移除后,保留键/值对可能更为合适。这可以通过使用 preserve 属性来实现:

加载实时示例

可组合函数

FormKit 提供了一些可组合函数来帮助你访问表单的数据和上下文。这些可从 @formkit/vue 包中导入:

useFormKitContext

useFormKitContext 是一个可组合函数,它返回表单的上下文对象作为 vue Ref,每当它变得可用时。这必须在 <FormKit> 组件的子组件中使用(如表单)。第一个参数是一个可选的遍历路径,它允许你导航到表单树中的任何节点。第二个参数是一个可选的效果回调,每当上下文变得可用时将被调用。

加载实时示例

useFormKitContextById

类似于 useFormKitContext,这个可组合函数会找到任何被赋予显式 id<FormKit> 上下文对象。你可以选择性地提供一个效果回调,每当节点变得可用时将被调用。

加载实时示例

useFormKitNodeById

获取任何被赋予显式 id 的 FormKit 节点。它返回一个 Ref,每当它被挂载时将填充核心节点。你可以选择性地提供一个效果回调,每当节点变得可用时将被调用。

加载实时示例
节点与上下文

节点本身不是响应式的,应该用于命令式操作,如 node.submit()。上下文对象是响应式的,应该用于读取和响应表单的状态。

属性 & 特性

表单在技术上被视为 input 类型 — 因此它们共享许多标准输入使用的通用属性。

PropType默认描述
disabledBooleanfalseDisables the form submit button and all the inputs in the form.
incomplete-messageString/Boolean{locale}.ui.incompleteThe message that is shown to near the submit button when a user attempts to submit a form, but not all inputs are valid.
submit-attrsObject{}Attributes or props that should be passed to the built-in submit button.
submit-behaviorStringdisabledAsync submit handlers automatically disable the form while pending, you can change this by setting this prop to 'live'.
submit-labelStringSubmitThe label to use on the built-in submit button.
actionsBooleantrueWhether or not to include the actions bar at the bottom of the form (ex. you want to remove the submit button and use your own, set this to false).
显示 通用 props
configObject{}提供给 input 的节点和此输入的任何后代节点的配置选项。
delayNumber20在调度 commit hook 前,输入值的去抖动毫秒数。
dirtyBehaviorstringtouched确定此输入的“dirty”标志设置方式。可以设置为 touchedcompare — 默认为 touched,性能更好,但无法检测表单是否再次匹配其初始状态。
errorsArray[]要在此字段上显示的错误消息的字符串数组。
helpString''帮助文本与输入关联的文本。
idStringinput_{n}输入的唯一标识符。提供一个 id 还可以全局访问输入的节点。
ignoreBooleanfalse防止将输入包含在任何父级(组、列表、表单等)中。在仅用于 UI 而不是实际值的情况下非常有用。
indexNumberundefined如果父级是列表,允许在给定索引处插入输入。如果输入的值未定义,它将继承该索引位置的值。如果它有一个值,它将在给定索引处将其插入到列表的值中。
labelString''与输入关联的 label 元素的文本。
nameStringinput_{n}输入的名称,在数据对象中唯一标识。在一组字段中应该是唯一的。
parentFormKitNodecontextual默认情况下,父级是包装组、列表或表单,但此属性允许显式分配父级节点。
prefix-iconString''指定放置在 prefixIcon 部分的 图标
preservebooleanfalse在输入卸载时,在父组、列表或表单上保留输入的值。
preserve-errorsbooleanfalse默认情况下,使用 setErrors 在输入上设置的错误会在输入时自动清除,将此属性设置为 true 可以保留错误,直到明确清除为止。
sections-schemaObject{}一个包含部分键和模式部分值的对象,其中每个模式部分应用于相应的部分。
suffix-iconString''指定放置在 suffixIcon 部分的 图标
typeStringtext要从库中渲染的输入类型。
validationString, Array[]要应用于输入的 验证 规则。
validation-visibilityStringblur确定何时显示输入的验证失败规则。有效值为 blurdirtylive
validation-labelString{label prop}确定在验证错误消息中使用的标签,默认情况下,如果可用,则使用 label 属性,否则使用 name 属性。
validation-rulesObject{}附加的自定义验证规则,可用于验证 prop。
valueAnyundefined为输入和/或其子元素提供初始值。不是响应式的。可以种子 整个组(表单)和列表。

章节

Section-key描述
form负责渲染 form 标签并监听提交事件。
actions负责表单底部的容器,包含表单操作如提交按钮。
submit负责提交按钮 — 默认为 FormKit 输入类型 submit
显示 通用 section keys
outer最外层的包装元素。
wrapper标签和输入周围的包装器。
label输入的标签。
prefix默认情况下没有输出,但允许直接在输入元素之前放置内容。
prefixIcon输出在前缀部分之前放置一个图标的元素。
inner实际输入元素周围的包装器。
suffix默认情况下没有输出,但允许直接在输入元素之后放置内容。
suffixIcon输出在后缀部分之后放置一个图标的元素。
input输入元素本身。
help包含帮助文本的元素。
messages包装所有消息的容器。
message包含消息的元素(或多个元素) - 最常见的是验证和错误消息。

可访问性

所有 FormKit 输入都是考虑到以下可访问性因素而设计的。通过在此处提交可访问性问题,帮助我们不断提高所有人的可访问性:

语义标记Aria 属性可通过键盘访问焦点指示器与提供的主题的颜色对比可访问标签、帮助文本和错误