虽然你可以单独使用 FormKit
输入,但你通常会想要将它们组合成一个表单。要做到这一点,只需将你的输入包裹在一个 <FormKit type="form">
中。
form
类型会主动收集所有子输入的值,使用每个输入的 name
作为结果数据对象中的属性名(就像 groups 一样)。你也可以使用 v-model 来读取和写入表单值,就像在任何输入上一样。
一个 <FormKit type="form">
跟踪表单的验证状态,并防止用户在任何输入无效时提交表单。
为了方便,form
自动输出一个提交 button,并且提供的主题也包括一个加载旋转器。你可以使用 submit-label
和 submit-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>
除了后端功能,这里是一个具有输入(form
、text
、email
、password
)、帮助文本、标签、自定义消息的验证以及错误和提交处理的完整功能表单:
你可以通过向 <FormKit type="form">
提供一个 value
属性来填充整个表单。value
属性应该是输入名称到输入值对的对象。如果你需要双向数据绑定,你也可以使用 v-model
来填充表单:
请确保 v-model
一个 ref
或者一个 reactive
对象的属性。不要 v-model
响应式对象本身,因为它会 导致意外行为。
表单通常通过用户操作来提交,例如点击提交按钮或在表单内的文本节点上按下 enter
键。提交时,表单会按顺序:
@submit-raw
事件。submitted
状态设置为 true — 显示任何剩余的验证错误(不管 validation-visibility
的设置)。@submit-invalid
事件。@submit
事件。@submit
处理器返回一个 Promise
,则将表单的状态设置为 loading
,直到它解决。在提交处理器中使用 v-model
数据可能会导致意外的表单变化。FormKit 自动 为您收集表单数据,因此请使用传递给您的提交处理器的未绑定副本的表单数据。
在现代单页应用程序中,表单提交的最常见方法是 XHR 请求(想想 axios 或 fetch)。FormKit 非常适合这项任务:
v-model
),以及 form
输入的核心节点,作为方便之用,交给您的 @submit
处理器。context.state.loading
的 loading
变为 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 时,你可以直接通过从核心导入 reset 函数来访问它:import { reset } from '@formkit/core'
。
需要注意的是,表单的“初始状态”并不一定是空表单。如果你在表单或表单中的个别输入项上有默认的 :value
或 v-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
配置选项来更改默认行为。这可以全局完成,或者针对单个表单完成:
当使用 Vue 3 的 composition API 时,你可以直接从 @formkit/vue
导入 setErrors
和 clearErrors
。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 />
组件有一些额外的配置选项:
属性 | 默认值 | 描述 |
---|---|---|
node | 继承 | 要为其渲染信息的核心节点。默认情况下,这是从节点的父级继承的(如果存在的话)。 |
sectionsSchema | {} | 覆盖内部的 messages 和 message 部分(与其他输入的消息部分相同的默认结构)。 |
defaultPosition | false | 默认情况下,FormKitMessages 将渲染的信息移动到一个新位置。如果你希望在两个位置都渲染信息,请将此属性设置为 true 。 |
当输入项从表单中卸载时 — 例如使用 v-if
— 其键和值会从表单的数据中移除。然而,在某些情况下,即使输入项被移除后,保留键/值对可能更为合适。这可以通过使用 preserve
属性来实现:
FormKit 提供了一些可组合函数来帮助你访问表单的数据和上下文。这些可从 @formkit/vue
包中导入:
useFormKitContext
是一个可组合函数,它返回表单的上下文对象作为 vue Ref
,每当它变得可用时。这必须在 <FormKit>
组件的子组件中使用(如表单)。第一个参数是一个可选的遍历路径,它允许你导航到表单树中的任何节点。第二个参数是一个可选的效果回调,每当上下文变得可用时将被调用。
类似于 useFormKitContext
,这个可组合函数会找到任何被赋予显式 id
的 <FormKit>
上下文对象。你可以选择性地提供一个效果回调,每当节点变得可用时将被调用。
获取任何被赋予显式 id
的 FormKit 节点。它返回一个 Ref
,每当它被挂载时将填充核心节点。你可以选择性地提供一个效果回调,每当节点变得可用时将被调用。
节点本身不是响应式的,应该用于命令式操作,如 node.submit()
。上下文对象是响应式的,应该用于读取和响应表单的状态。
表单在技术上被视为 input
类型 — 因此它们共享许多标准输入使用的通用属性。
Prop | Type | 默认 | 描述 |
---|---|---|---|
disabled | Boolean | false | Disables the form submit button and all the inputs in the form. |
incomplete-message | String/Boolean | {locale}.ui.incomplete | The message that is shown to near the submit button when a user attempts to submit a form, but not all inputs are valid. |
submit-attrs | Object | {} | Attributes or props that should be passed to the built-in submit button. |
submit-behavior | String | disabled | Async submit handlers automatically disable the form while pending, you can change this by setting this prop to 'live'. |
submit-label | String | Submit | The label to use on the built-in submit button. |
actions | Boolean | true | Whether 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 | |||
config | Object | {} | 提供给 input 的节点和此输入的任何后代节点的配置选项。 |
delay | Number | 20 | 在调度 commit hook 前,输入值的去抖动毫秒数。 |
dirtyBehavior | string | touched | 确定此输入的“dirty”标志设置方式。可以设置为 touched 或 compare — 默认为 touched ,性能更好,但无法检测表单是否再次匹配其初始状态。 |
errors | Array | [] | 要在此字段上显示的错误消息的字符串数组。 |
help | String | '' | 帮助文本与输入关联的文本。 |
id | String | input_{n} | 输入的唯一标识符。提供一个 id 还可以全局访问输入的节点。 |
ignore | Boolean | false | 防止将输入包含在任何父级(组、列表、表单等)中。在仅用于 UI 而不是实际值的情况下非常有用。 |
index | Number | undefined | 如果父级是列表,允许在给定索引处插入输入。如果输入的值未定义,它将继承该索引位置的值。如果它有一个值,它将在给定索引处将其插入到列表的值中。 |
label | String | '' | 与输入关联的 label 元素的文本。 |
name | String | input_{n} | 输入的名称,在数据对象中唯一标识。在一组字段中应该是唯一的。 |
parent | FormKitNode | contextual | 默认情况下,父级是包装组、列表或表单,但此属性允许显式分配父级节点。 |
prefix-icon | String | '' | 指定放置在 prefixIcon 部分的 图标。 |
preserve | boolean | false | 在输入卸载时,在父组、列表或表单上保留输入的值。 |
preserve-errors | boolean | false | 默认情况下,使用 setErrors 在输入上设置的错误会在输入时自动清除,将此属性设置为 true 可以保留错误,直到明确清除为止。 |
sections-schema | Object | {} | 一个包含部分键和模式部分值的对象,其中每个模式部分应用于相应的部分。 |
suffix-icon | String | '' | 指定放置在 suffixIcon 部分的 图标。 |
type | String | text | 要从库中渲染的输入类型。 |
validation | String, Array | [] | 要应用于输入的 验证 规则。 |
validation-visibility | String | blur | 确定何时显示输入的验证失败规则。有效值为 blur 、dirty 和 live 。 |
validation-label | String | {label prop} | 确定在验证错误消息中使用的标签,默认情况下,如果可用,则使用 label 属性,否则使用 name 属性。 |
validation-rules | Object | {} | 附加的自定义验证规则,可用于验证 prop。 |
value | Any | undefined | 为输入和/或其子元素提供初始值。不是响应式的。可以种子 整个组(表单)和列表。 |
Section-key | 描述 |
---|---|
form | 负责渲染 form 标签并监听提交事件。 |
actions | 负责表单底部的容器,包含表单操作如提交按钮。 |
submit | 负责提交按钮 — 默认为 FormKit 输入类型 submit 。 |
显示 通用 section keys | |
outer | 最外层的包装元素。 |
wrapper | 标签和输入周围的包装器。 |
label | 输入的标签。 |
prefix | 默认情况下没有输出,但允许直接在输入元素之前放置内容。 |
prefixIcon | 输出在前缀部分之前放置一个图标的元素。 |
inner | 实际输入元素周围的包装器。 |
suffix | 默认情况下没有输出,但允许直接在输入元素之后放置内容。 |
suffixIcon | 输出在后缀部分之后放置一个图标的元素。 |
input | 输入元素本身。 |
help | 包含帮助文本的元素。 |
messages | 包装所有消息的容器。 |
message | 包含消息的元素(或多个元素) - 最常见的是验证和错误消息。 |
所有 FormKit 输入都是考虑到以下可访问性因素而设计的。通过在此处提交可访问性问题,帮助我们不断提高所有人的可访问性: