PrimeVue 表單函式庫提供全面的表單狀態管理,並內建驗證支援。
表單附加元件可在 npm 註冊表中下載。
# Using npm
npm install @primevue/forms
# Using yarn
yarn add @primevue/forms
# Using pnpm
pnpm add @primevue/forms
表單元件負責管理表單狀態,且必須封裝表單欄位。
import { Form } from '@primevue/forms';
所有 PrimeVue 表單元件都設計為可與表單函式庫無縫整合。不是使用標準的 v-model,而是使用 name 屬性連結追蹤值、錯誤和動作的狀態物件。表單元件提供四個用於狀態管理的關鍵屬性。
屬性 | 描述 |
---|---|
v-slot="$form" | 公開追蹤欄位狀態管理的主要 $form 物件。 |
initialValues | 指定要初始化表單的預設值。 |
resolver | 驗證處理程式,用於實作驗證或繫結像是 Zod、Yup、Valibot 等架構。 |
@submit | 表單提交時要執行的事件處理程式。 |
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<div class="flex flex-col gap-1">
<InputText name="username" type="text" placeholder="Username" fluid />
<Message v-if="$form.username?.invalid" severity="error" size="small" variant="simple">{{ $form.username.error?.message }}</Message>
</div>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
$form 物件會追蹤欄位的狀態管理。每個欄位都與 name 屬性連結。檢視 API 文件中的 FormFieldState 類型,以了解每個屬性的詳細資訊。
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="grid lg:grid-cols-2 gap-4 w-full">
<div class="flex flex-col justify-center items-center gap-4">
<InputText name="username" type="text" placeholder="Username" class="w-full sm:w-56" />
<Button type="submit" severity="secondary" label="Submit" class="w-full sm:w-56" />
</div>
<Fieldset legend="Form States" class="h-80 overflow-auto">
<pre class="whitespace-pre-wrap">{{ $form }}</pre>
</Fieldset>
</Form>
驗證是使用 resolver 屬性實作的。自訂解析器負責處理驗證並傳回一個 errors 物件,其中包含鍵值對,其中鍵是表單欄位名稱,值是錯誤物件資料陣列。為提高生產力,我們建議使用架構驗證函式庫,而不是建立自己的自訂驗證邏輯。表單函式庫為熱門選項提供內建解析器,包括 Zod、Yup、Joi、Valibot 和 Superstruct,這些解析器可以從 @primevue/forms/resolvers 路徑匯入。
<Form v-slot="$form" :initialValues :resolver="resolver" @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<div class="flex flex-col gap-1">
<InputText name="username" type="text" placeholder="Username" fluid />
<Message v-if="$form.username?.invalid" severity="error" size="small" variant="simple">{{ $form.username.error.message }}</Message>
</div>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
表單元件支援彈性的驗證觸發器,允許在值更新、失去焦點事件、表單掛載或提交時進行驗證。這些行為可以在表單層級或透過 formControl 屬性的 validateOnValueUpdate、validateOnBlur、validateOnMount 和 validateOnSubmit 選項在特定欄位上配置。
在此範例中,表單會在表單層級停用 validateOnValueUpdate 並啟用 validateOnBlur,並在掛載時驗證 firstName。firstName 欄位會在本地覆寫表單層級設定。
<Form v-slot="$form" :initialValues :resolver :validateOnValueUpdate="false" :validateOnBlur="true" :validateOnMount="['firstName']" @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<div class="flex flex-col gap-1">
<InputText name="username" type="text" placeholder="Username" fluid />
<Message v-if="$form.username?.invalid" severity="error" size="small" variant="simple">{{ $form.username.error.message }}</Message>
</div>
<div class="flex flex-col gap-1">
<InputText name="firstName" type="text" placeholder="First Name" fluid :formControl="{ validateOnValueUpdate: true }" />
<Message v-if="$form.firstName?.invalid" severity="error" size="small" variant="simple">{{ $form.firstName.error.message }}</Message>
</div>
<div class="flex flex-col gap-1">
<InputText name="lastName" type="text" placeholder="Last Name" fluid />
<Message v-if="$form.lastName?.invalid" severity="error" size="small" variant="simple">{{ $form.lastName.error.message }}</Message>
</div>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
FormField 是一個輔助元件,可為輸入元素提供驗證和追蹤,提供更彈性的結構,以將 PrimeVue、非 PrimeVue 元件或原生 HTML 元素繫結至 Form API。此外,透過像是 validateOn*、initialValue、resolver 和 name 等 props,可以直接從此元件控制行為。
import { FormField } from '@primevue/forms';
雖然 PrimeVue 元件對 Form API 有內建支援,您可能仍然偏好將元件與 FormField 包裹在一起使用。這是一個偏好問題,例如,如果您也將 FormField 用於其他第三方元件、您自己的自訂元件和原生元素,為了保持一致性,這可能會是一個選項。
<Form :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<FormField v-slot="$field" name="username" initialValue="" class="flex flex-col gap-1">
<InputText type="text" placeholder="Username" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
Form API 並非嚴格繫結到 PrimeVue 元件,它提供了一種彈性的方式來管理任何原生 HTML 元素、您自己的自訂元件或第三方函式庫的驗證和狀態。
<Form :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<FormField v-slot="$field" name="username" initialValue="" class="flex flex-col gap-1">
<input type="text" placeholder="Username" :class="[{ error: $field?.invalid }]" v-bind="$field.props" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="password" initialValue="PrimeVue" class="flex flex-col gap-1">
<input v-model="$field.value" type="password" placeholder="Password" :class="[{ error: $field?.invalid }]" @input="$field.onInput" @blur="$field.onBlur" @change="$field.onChange" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
每個 FormField 都可以有自己的專用解析器,允許您為個別欄位定義自訂驗證邏輯。這種彈性可以實現客製化的驗證規則,確保每個表單欄位都符合特定條件。
<Form :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-80">
<FormField v-slot="$field" name="username" initialValue="" :resolver="zodUserNameResolver" class="flex flex-col gap-1">
<InputText type="text" placeholder="Username" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="firstname" initialValue="" :resolver="yupFirstNameResolver" class="flex flex-col gap-1">
<InputText type="text" placeholder="First Name" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="lastname" initialValue="" :resolver="valibotLastNameResolver" class="flex flex-col gap-1">
<InputText type="text" placeholder="Last Name" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="password" initialValue="" :resolver="customPasswordResolver" class="flex flex-col gap-1">
<Password type="text" placeholder="Password" :feedback="false" toggleMask fluid />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" name="details" class="flex flex-col gap-1">
<Textarea placeholder="Details" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
它會呈現為 HTML div 元素,但可以使用 as 和 asChild props 修改此行為,以呈現不同的 HTML 元素或傳遞自訂元件,從而提供更高的表單結構彈性。
<Form :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-56">
<FormField v-slot="$field" as="section" name="username" initialValue="" class="flex flex-col gap-2">
<InputText type="text" placeholder="Username" />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</FormField>
<FormField v-slot="$field" asChild name="password" initialValue="">
<section class="flex flex-col gap-2">
<Password type="text" placeholder="Password" :feedback="false" toggleMask fluid />
<Message v-if="$field?.invalid" severity="error" size="small" variant="simple">{{ $field.error?.message }}</Message>
</section>
</FormField>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
submit 回呼會傳回一個物件,其中封裝了表單的有效性、任何現有的錯誤及其目前狀態。這樣就可以在提交時存取表單值、驗證狀態和任何存在的錯誤。檢視 API 文件中的 FormSubmitEvent,以取得有關可用事件資料的詳細資訊。
<Form v-slot="$form" :initialValues :resolver @submit="onFormSubmit" class="flex flex-col gap-4 w-full sm:w-60">
<div class="flex flex-col gap-1">
<InputText name="username" type="text" placeholder="Username" fluid />
<Message v-if="$form.username?.invalid" severity="error" size="small" variant="simple">{{ $form.username.error.message }}</Message>
</div>
<div class="flex flex-col gap-1">
<Password name="password" placeholder="Password" :feedback="false" toggleMask fluid />
<Message v-if="$form.password?.invalid" severity="error" size="small" variant="simple">
<ul class="my-0 px-4 flex flex-col gap-1">
<li v-for="(error, index) of $form.password.errors" :key="index">{{ error.message }}</li>
</ul>
</Message>
</div>
<Button type="submit" severity="secondary" label="Submit" />
</Form>
本節示範如何使用自訂的 Form 元件建立動態表單。它展示了一個範例,其中表單欄位是根據提供的配置動態產生的,允許彈性的表單結構。此範例中顯示的名稱為 Dynamic* 的元件並非內建,僅適用於取樣目的。第一個表單使用宣告式方法,而第二個表單則採用程式化方法。我們建議在 StackBlitz 中執行此範例,以檢視完整的實作。
<Fieldset legend="Form 1" pt:content:class="flex justify-center">
<DynamicForm @submit="onFormSubmit('Form 1', $event)">
<DynamicFormField groupId="userId_1" name="username">
<DynamicFormLabel>Username</DynamicFormLabel>
<DynamicFormControl defaultValue="PrimeVue" fluid :schema="userNameSchema" />
<DynamicFormMessage />
</DynamicFormField>
<DynamicFormField groupId="passId_1" name="password">
<DynamicFormLabel>Password</DynamicFormLabel>
<DynamicFormControl as="Password" :feedback="false" toggleMask fluid :schema="passwordSchema" />
<DynamicFormMessage errorType="minimum" />
<DynamicFormMessage errorType="maximum" />
<DynamicFormMessage errorType="uppercase" severity="warn" />
<DynamicFormMessage errorType="lowercase" severity="warn" />
<DynamicFormMessage errorType="number" severity="secondary" />
</DynamicFormField>
<DynamicFormSubmit />
</DynamicForm>
</Fieldset>
<Fieldset legend="Form 2" pt:content:class="flex justify-center">
<DynamicForm :fields @submit="onFormSubmit('Form 2', $event)" />
</Fieldset>
表單不需要任何角色和屬性。
元件不包含任何互動式元素。