Form
Used to collect information.
Basic usage
Form uses model to pass the form data object and rules to pass validation rules; in FormItem, field sets the form item field for validation, reset, and other operations.
FormItem's
ruletakes precedence over Form'srulesfor the samefield.
When manually triggering validation using the Form component's
validatemethod, it ignores thetriggercondition configured onrulesorrule, validates all existing FormItems, and stops at the first failing rule.
Additionally, note that the
fieldproperty of FormItem is not reactive.
<template>
<px-form
:model="form"
:rules="rules"
style="width: 500px"
@submit="submitHandler"
ref="formRef"
>
<px-form-item label="Input" field="input">
<px-input v-model="form.input" placeholder="Please input..."></px-input>
</px-form-item>
<px-form-item label="Radio" field="radio">
<px-radio-group
v-model="form.radio"
:options="radioOptions"
variant="retro"
></px-radio-group>
</px-form-item>
<px-form-item label="Checkbox" field="checkbox">
<px-checkbox-group v-model="form.checkbox" :options="checkboxOptions"></px-checkbox-group>
</px-form-item>
<px-form-item label="Number" field="number">
<px-input-number v-model="form.number" placeholder="Please input..."></px-input-number>
</px-form-item>
<px-form-item label="Tags" field="tags">
<px-input-tag v-model="form.tags" placeholder="Press enter to confirm..."></px-input-tag>
</px-form-item>
<px-form-item label="Text" field="text">
<px-textarea v-model="form.text" placeholder="Please input text..."></px-textarea>
</px-form-item>
<px-form-item label="Switch" field="switch">
<px-switch v-model="form.switch"></px-switch>
</px-form-item>
<px-form-item label="Select" field="select">
<px-select
:options="options"
v-model="form.select"
placeholder="Please select..."
></px-select>
</px-form-item>
<px-form-item label="Nest" field="nest.value">
<px-input v-model="form.nest.value" placeholder="Please input..."></px-input>
</px-form-item>
<px-form-item label="Email" field="email">
<px-input v-model="form.email" placeholder="Please email..."></px-input>
</px-form-item>
<px-form-item label="URL" field="url">
<px-input v-model="form.url" placeholder="Please URL..."></px-input>
</px-form-item>
<px-form-item label="Slider" field="slider">
<px-slider v-model="form.slider"></px-slider>
</px-form-item>
<px-form-item label="Number String" field="numberString">
<px-input v-model="form.numberString" placeholder="Please number..."></px-input>
</px-form-item>
<px-space justify="end">
<px-button native-type="submit">Submit</px-button>
<px-button theme="info" native-type="reset" style="margin-left: 8px">Reset</px-button>
</px-space>
</px-form>
</template>
<script setup lang="ts">
import { Form } from '@pixelium/web-vue'
// If on-demand import
// import { Form } from '@pixelium/web-vue/es'
import { ref, shallowRef } from 'vue'
const form = ref({
input: '',
number: 0,
tags: [] as string[],
text: '',
nest: {
value: ''
},
select: null as null | string,
email: '',
url: '',
numberString: '',
switch: false,
radio: null as null | string,
checkbox: [] as string[],
slider: 10
})
const rules = {
input: { required: true, message: 'Please input' },
select: { required: true, message: 'Please select' },
switch: { required: true, message: 'Please select' },
number: { min: 10, message: 'Min is 10' },
tags: [
{ required: true, message: 'Please input tags' },
{ maxLength: 5, message: 'Length less than or equal 5' }
],
text: { required: true, message: 'Just a tip', level: 'warning' },
'nest.value': { required: true, message: 'Please input' },
email: { required: true, email: true, message: 'Please input email' },
url: { required: true, url: true, message: 'Please input a URL' },
numberString: { required: true, numberString: true, message: 'Please input number' },
radio: {
required: true,
validator(value: string) {
return value !== 'Yes' ? 'Please select Yes' : undefined
}
},
checkbox: [
{ required: true, message: 'Please select' },
{ maxLength: 2, message: 'You can select up to 2 items' }
],
slider: { max: 90, message: 'Max is 90' }
}
const options = ref(['vue', 'react', 'angular'])
const radioOptions = ref(['Yes', 'No'])
const checkboxOptions = ref(['A', 'B', 'C', 'D'])
const formRef = shallowRef<null | InstanceType<typeof Form>>(null)
const submitHandler = () => {
formRef.value?.validate().then(({ isValid }) => {
if (isValid) {
console.log('submit')
}
})
}
</script>useForm returns an object for manipulating the form, which can be passed to the Form's form property.
Either the
modelorformproperty of Form must be provided.
<template>
<div style="width: 500px">
<px-form :form="userForm" :rules="userRules" label-auto-width>
<px-form-item field="username" label="Username">
<px-input v-model="userForm.model.value.username" placeholder="Username"></px-input>
</px-form-item>
<px-form-item field="email" label="Email">
<px-input v-model="userForm.model.value.email" placeholder="Email"></px-input>
</px-form-item>
<px-space justify="end">
<px-button @click="handleClearValidationUser" theme="info">Clear Validation</px-button>
<px-button @click="handleResetUser" theme="warning">Reset</px-button>
<px-button @click="handleSubmitUser">Submit</px-button>
</px-space>
</px-form>
</div>
</template>
<script setup lang="ts">
import { useForm } from '@pixelium/web-vue'
// When on-demand import
// import { useForm } from '@pixelium/web-vue/es'
const userForm = useForm({
initialValues: { username: '', email: '' }
})
const userRules = {
username: [{ required: true, message: 'Please input username' }],
email: [{ required: true, email: true, message: 'Please input valid email' }]
}
const handleSubmitUser = () => {
userForm.validate().then(({ isValid }) => {
if (isValid) {
console.log('Submit User Form')
}
})
}
const handleResetUser = () => {
userForm.reset()
}
const handleClearValidationUser = () => {
userForm.clearValidation()
}
</script>Custom validation
Use validator to provide custom validation rules.
<template>
<px-form :model="form" :rules="rules" style="width: 600px" ref="formRef">
<p>The Answer to the Great Question Of Life, the Universe and Everything...</p>
<px-form-item label="Answer" field="number" label-align="left">
<px-input-number v-model="form.number"></px-input-number>
</px-form-item>
</px-form>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const form = ref({
number: 0
})
const rules = {
number: {
validator: (value: number | null) => {
if (value === 42) {
return
}
return 'Could you think again?'
}
}
}
</script>Disabled & Readonly
Set the form's disabled state using disabled and the readonly state using readonly.
The
disabledorreadonlyattribute of the Form component affects all button components within it (including Button and ButtonGroup) and the data input components within each FormItem, while thedisabledorreadonlyattribute of an individual FormItem only affects the button and data input components within that specific FormItem.
These two properties follow an 'OR' logic throughout the component hierarchy: if any level—Form, FormItem, or the component itself—is set to disabled or readonly, the component will be rendered in that state.
<template>
<px-space>
<px-form
:model="form"
:rules="rules"
style="width: 500px"
@submit="submitHandler"
ref="formRef"
disabled
>
<h4>Disabled</h4>
<px-form-item label="Username" field="username">
<px-input v-model="form.username" placeholder="Please input username..."></px-input>
</px-form-item>
<px-form-item label="Email" field="email">
<px-input v-model="form.email" placeholder="Please email..."></px-input>
</px-form-item>
<px-space justify="end">
<px-button native-type="submit">Submit</px-button>
<px-button theme="info" native-type="reset" style="margin-left: 8px">Reset</px-button>
</px-space>
</px-form>
<px-form
:model="form"
:rules="rules"
style="width: 500px"
@submit="submitHandler"
ref="formRef"
readonly
>
<h4>Readonly</h4>
<px-form-item label="Username" field="username">
<px-input v-model="form.username" placeholder="Please input username..."></px-input>
</px-form-item>
<px-form-item label="Email" field="email">
<px-input v-model="form.email" placeholder="Please email..."></px-input>
</px-form-item>
<px-space justify="end">
<px-button native-type="submit">Submit</px-button>
<px-button theme="info" native-type="reset" style="margin-left: 8px">Reset</px-button>
</px-space>
</px-form>
</px-space>
</template>
<script setup lang="ts">
import { Form } from '@pixelium/web-vue'
// If on-demand import
// import { Form } from '@pixelium/web-vue/es'
import { ref, shallowRef } from 'vue'
const form = ref({
username: '',
email: ''
})
const rules = {
username: { required: true, message: 'Please input' },
email: { required: true, email: true, message: 'Please input email' }
}
const formRef = shallowRef<null | InstanceType<typeof Form>>(null)
const submitHandler = () => {
formRef.value?.validate().then(({ isValid }) => {
if (isValid) {
console.log('submit')
}
})
}
</script>Label alignment
Set label alignment with labelAlign.
<template>
<px-space direction="vertical">
<px-form :model="form" label-align="top" style="width: 500px">
<px-form-item label="Input" field="input">
<px-input v-model="form.input"></px-input>
</px-form-item>
</px-form>
<px-form :model="form" style="width: 500px" label-align="left">
<px-form-item label="Input" field="input">
<px-input v-model="form.input"></px-input>
</px-form-item>
</px-form>
<px-form :model="form" style="width: 500px">
<px-form-item label="Input" field="input">
<px-input v-model="form.input"></px-input>
</px-form-item>
</px-form>
</px-space>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const form = ref({
input: ''
})
</script>Child element width
Use labelProps and contentProps to modify the Col component props for the label and content areas.
When labelAutoWidth is set, the label area width becomes adaptive and the content area width will change accordingly.
<template>
<px-space direction="vertical">
<px-form
:model="form"
style="width: 500px"
:label-props="{ span: 4 }"
:content-props="{ span: 20 }"
>
<px-form-item label="Input" field="input">
<px-input v-model="form.input"></px-input>
</px-form-item>
</px-form>
<px-form :model="form" style="width: 500px" label-auto-width>
<px-form-item label="Input" field="input">
<px-input v-model="form.input"></px-input>
</px-form-item>
</px-form>
</px-space>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const form = ref({
input: ''
})
</script>Form size
The form is available in different sizes.
The
sizeproperty of the Form component affects all button components within it (including Button and ButtonGroup) and the data input components within each FormItem.
For button components and data input components inside Form and FormItem, if the
sizeproperty is not provided or isundefined, it will be set to match the Form'ssizeproperty; if explicitly set, the provided value takes precedence.
<template>
<px-space direction="vertical">
<px-radio-group v-model="formSize" :options="radioSizeOptions"></px-radio-group>
<px-form
label-auto-width
:model="form"
:size="formSize"
style="width: 500px"
@submit="submitHandler"
>
<px-form-item label="Input" field="input">
<px-input v-model="form.input"></px-input>
</px-form-item>
<px-form-item label="Number" field="number">
<px-input-number v-model="form.number"></px-input-number>
</px-form-item>
<px-form-item label="Radio" field="radio">
<px-radio-group
v-model="form.radio"
:options="radioOptions"
variant="retro"
></px-radio-group>
</px-form-item>
<px-form-item label="Checkbox" field="checkbox">
<px-checkbox-group
v-model="form.checkbox"
:options="checkboxOptions"
></px-checkbox-group>
</px-form-item>
<px-form-item label="Switch" field="switch">
<px-switch v-model="form.switch"></px-switch>
</px-form-item>
<px-space justify="end">
<px-button native-type="submit">Submit</px-button>
</px-space>
</px-form>
</px-space>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const form = ref({
input: 'text',
number: 114,
radio: 'Yes',
switch: false,
checkbox: [] as string[]
})
const submitHandler = () => {
console.log('submit')
}
const radioOptions = ref(['Yes', 'No'])
const radioSizeOptions = ref([
{ label: 'Small', value: 'small' },
{ label: 'Medium', value: 'medium' },
{ label: 'Large', value: 'large' }
])
const checkboxOptions = ref(['A', 'B', 'C', 'D'])
const formSize = ref('medium')
</script>API
useForm
function useForm<T extends Record<string | number, any> = Record<string | number, any>>(options?: {
initialValues?: T;
}): UseFormReturn<T>
export interface UseFormReturn<
T extends Record<string | number, any> = Record<string | number, any>
> {
model: Ref<T>
validate: (field?: string | string[]) => FormValidateResult
reset: (field?: string | string[]) => void
clearValidation: (field?: string | string[]) => void
register: (registerOptions: UseFormRegisterOptions) => void
}FormProps
| Attribute | Type | Optional | Default | Description | Version |
|---|---|---|---|---|---|
| model | Record<number | string, any> | True | | The form data object. Either form or model must be provided. | 0.0.3 |
| form | FormInstance | True | | Form object returned by useForm, used to manipulate the form via a hook. Either form or model must be provided. | 0.0.3 |
| rules | Record<string, RuleItem | RuleItem[]> | True | | Validation rules. | 0.0.3 |
| disabled | boolean | True | false | Whether the form is disabled. | 0.0.3 |
| readonly | boolean | True | false | Whether the form is read-only. | 0.0.3 |
| size | 'small' | 'medium' | 'large' | True | 'medium' | Form size. | 0.0.3 |
| labelAlign | 'left' | 'right' | 'top' | True | 'right' | Label alignment. | 0.0.3 |
| showAsterisk | boolean | True | | Whether to show an asterisk. | 0.0.3 |
| asteriskPlacement | 'left' | 'right' | 'end' | True | 'left' | Position of the asterisk. | 0.0.3 |
| labelAutoWidth | boolean | True | false | Enable auto width for form item labels. | 0.0.3 |
| rowProps | RowProps | True | | Props for the form item row container. | 0.0.3 |
| labelProps | ColProps | True | | Props for the form item's label column. | 0.0.3 |
| contentProps | ColProps | True | | Props for the form item's content column. | 0.0.3 |
UseFormReturn
| Attribute | Type | Optional | Default | Description | Version |
|---|---|---|---|---|---|
| model | Ref<Record<string | number, any>> | False | | The form data object. | 0.0.3 |
| validate | (field?: string | string[]) => FormValidateResult | False | | Manually triggers form validation. Validates all fields when no parameters are provided. Can only be called after the Form is mounted. | 0.0.3 |
| reset | (field?: string | string[]) => void | False | | Manually triggers form reset. Resets all fields when no parameters are provided. Can only be called after the Form is mounted. | 0.0.3 |
| clearValidation | (field?: string | string[]) => void | False | | Clears the form validation status. Clears validation for all fields when no parameters are provided. Can only be called after the Form is mounted. | 0.0.3 |
FormEvents
| Event | Parameter | Description | Version |
|---|---|---|---|
| submit | form: Record<number | string, any>, event: Event | Callback for native form submit. | 0.0.3 |
| reset | form: Record<number | string, any>, event: Event | Callback for native form reset. | 0.0.3 |
FormSlots
| Slot | Parameter | Description | Version |
|---|---|---|---|
| default | | Used to render form items. | 0.0.3 |
FormExpose
| Attribute | Type | Optional | Default | Description | Version |
|---|---|---|---|---|---|
| validate | (field?: string | string[]) => FormValidateResult | False | | Manually trigger form validation; without arguments validates all fields. | 0.0.3 |
| reset | (field?: string | string[]) => void | False | | Manually trigger form reset; without arguments resets all fields. | 0.0.3 |
| clearValidation | (field?: string | string[]) => void | False | | Clear validation state; without arguments clears all fields. | 0.0.3 |
RuleItem
| Attribute | Type | Optional | Default | Description | Version |
|---|---|---|---|---|---|
| required | boolean | True | false | Whether the field is required. | 0.0.3 |
| message | string | True | | Error message shown on validation failure; an empty string will not trigger an error. | 0.0.3 |
| trigger | RuleTrigger | RuleTrigger[] | True | ['change', 'blur'] | Event that triggers validation. | 0.0.3 |
| type | FieldType | FieldType[] | True | | Field type validation. | 0.0.3 |
| max | number | True | | Maximum value limit, only for numeric values. | 0.0.3 |
| min | number | True | | Minimum value limit, only for numeric values. | 0.0.3 |
| maxLength | number | True | | Maximum length limit, applicable when the value is a string or array. | 0.0.3 |
| minLength | number | True | | Minimum length limit, applicable when the value is a string or array. | 0.0.3 |
boolean | True | false | Whether the value must be an email address (applies when value is a string). | 0.0.3 | |
| url | boolean | True | false | Whether the value must be a URL (applies when value is a string). | 0.0.3 |
| numberString | boolean | True | false | Whether the value must be a numeric string (applies when value is a string). | 0.0.3 |
| level | RuleLevel | True | 'error' | Failure level; only 'error' will cause the form validation to fail. | 0.0.3 |
| validator | (value: any, model: Record<number | string, any>) => string | void | Promise<void | string> | True | | Custom validation function that returns an error message string; a falsy/empty return indicates success. | 0.0.3 |
FormItemProps
| Attribute | Type | Optional | Default | Description | Version |
|---|---|---|---|---|---|
| field | string | True | | The associated form field name. Supports field path syntax, e.g. 'user[0].info.name'. This property is not reactive. | 0.0.3 |
| label | string | True | | Label text. | 0.0.3 |
| rule | RuleItem | RuleItem[] | True | | Validation rules. | 0.0.3 |
| disabled | boolean | True | | Whether to disable. The final disabled state is determined by OR operation with disabled from Form. | 0.0.3 |
| readonly | boolean | True | | Whether to be read-only. The final read-only state is determined by OR operation with readonly from Form. | 0.0.3 |
| labelAlign | 'left' | 'right' | 'top' | True | | Label alignment for this item. | 0.0.3 |
| showAsterisk | boolean | True | | Whether to show an asterisk. | 0.0.3 |
| asteriskPlacement | 'left' | 'right' | 'end' | True | | Position of the asterisk. | 0.0.3 |
| rowProps | RowProps | True | | Props for the form item's row container. | 0.0.3 |
| labelProps | ColProps | True | | Props for the form item's label column. | 0.0.3 |
| contentProps | ColProps | True | | Props for the form item's content column. | 0.0.3 |
FormItemSlots
| Slot | Parameter | Description | Version |
|---|---|---|---|
| tip | message: string, level: RuleLevel | Validation tip slot. | 0.0.3 |
| extra | | Extra content slot located below the content area. | 0.0.3 |
| label | | Custom label slot. | 0.0.3 |
| default | | Form item content slot. | 0.0.3 |
RuleLevel, FieldType, RuleTrigger, FormValidateResult
export type RuleLevel = 'error' | 'warning' | 'success' | 'normal'
export type FieldType = 'number' | 'string' | 'boolean' | 'array' | 'dict' | 'function' | 'date'
export type RuleTrigger = 'blur' | 'change' | 'input'
export type FormValidateResult = Promise<{
isValid: boolean
results: Record<
string,
PromiseSettledResult<{
message: string
level: RuleLevel
}>
>
}>