Form
17:06Description
A form validation container that works with any input component. ux-form collects the ux-form-items inside it, provides model / rules / error-type / label-* / size down to them, and exposes validate(), resetFields(), and setRules(); ux-form-item is a single field bound to a model property via prop (nested paths like a.b are supported). It renders the label, required asterisk, left/right icons and error message, and triggers validation on blur / change according to each rule's trigger. The two cooperate through provide/inject, and a form item can host any input component such as ux-input, ux-textarea, ux-radio-group, ux-checkbox-group, or ux-picker.
Compatibility
| Platform | Support |
|---|---|
| App | ✅ Supported |
| H5 | ✅ Supported |
| WeChat Mini Program | ✅ Supported |
Examples
Basic Usage
Configure rules via rules, validate all fields with validate(), and reset with resetFields().
View source
<template>
<ux-form ref="formRef" :model="model" :rules="rules" :error-type="['message']" label-position="left">
<ux-form-item label="姓名" prop="name" required left-icon="account">
<ux-input v-model="model.name" placeholder="请输入姓名" border />
</ux-form-item>
<ux-form-item label="密码" prop="password">
<ux-input v-model="model.password" type="password" :password-icon="true" placeholder="请输入密码" border />
</ux-form-item>
<ux-form-item label="手机号" prop="phone">
<ux-input v-model="model.phone" type="number" placeholder="请输入手机号" border />
</ux-form-item>
<ux-form-item label="性别" prop="sex">
<ux-input v-model="model.sex" type="select" :select-open="pickerShow" placeholder="请选择性别" border @click="pickerShow = true" />
</ux-form-item>
</ux-form>
<ux-button type="primary" @click="onSubmit">提交</ux-button>
<ux-button type="default" @click="onReset">重置</ux-button>
<ux-picker v-model="pickerShow" mode="selector" :columns="columns" @confirm="onConfirm" />
</template>
<script setup lang="uts">
import type { FormRule } from '@/uni_modules/uview-pro-x';
import type { PickerOption } from '@/uni_modules/uview-pro-x';
const formRef = ref<any | null>(null);
const pickerShow = ref<boolean>(false);
const model = ref<UTSJSONObject>(new UTSJSONObject());
model.value['name'] = '';
model.value['password'] = '';
model.value['phone'] = '';
model.value['sex'] = '';
const rules = ref<Map<string, FormRule[]>>(new Map([
['name', [
{ required: true, message: '请输入姓名', trigger: 'blur' },
{ min: 2, max: 5, message: '姓名长度在 2 到 5 个字符', trigger: 'change' }
]],
['password', [
{ required: true, message: '请输入密码', trigger: 'blur' }
]],
['phone', [
{ required: true, message: '请输入手机号', trigger: 'blur' },
{
validator: (value: any | null): boolean | string => {
if (value == null || value === '') return true;
if (String(value).length !== 11) return '手机号码不正确';
return true;
},
trigger: 'change'
}
]],
['sex', [{ required: true, message: '请选择性别', trigger: 'change' }]]
]));
const columns: PickerOption[][] = [
[
{ text: '男', value: 'male' },
{ text: '女', value: 'female' }
]
];
const onSubmit = () => {
formRef.value?.validate().then((valid: boolean) => {
if (valid) {
uni.showToast({ title: '提交成功', icon: 'success' });
} else {
uni.showToast({ title: '校验失败', icon: 'none' });
}
});
};
const onReset = () => {
formRef.value?.resetFields();
};
const onConfirm = (event: UTSJSONObject): void => {
const options = event['selectedOptions'] as PickerOption[];
if (options != null && options.length > 0) {
model.value['sex'] = options[0].text;
}
};
</script>Configuration
View source
<template>
<ux-form :model="model" :error-type="errorType" :label-position="labelPosition">
<ux-form-item label="错误提示方式" prop="name">
<ux-input v-model="model.name" placeholder="触发校验查看错误提示" border />
</ux-form-item>
</ux-form>
<view class="btn-wrap">
<ux-button size="small" :type="errorType[0] === 'message' ? 'primary' : 'default'" @click="setErrorType('message')">message</ux-button>
<ux-button size="small" :type="errorType[0] === 'toast' ? 'primary' : 'default'" @click="setErrorType('toast')">toast</ux-button>
<ux-button size="small" :type="labelPosition === 'top' ? 'primary' : 'default'" @click="labelPosition = 'top'">标签在上</ux-button>
<ux-button size="small" :type="labelPosition === 'left' ? 'primary' : 'default'" @click="labelPosition = 'left'">标签在左</ux-button>
</view>
</template>
<script setup lang="uts">
import type { FormErrorType } from '@/uni_modules/uview-pro-x';
const model = ref<UTSJSONObject>(new UTSJSONObject());
model.value['name'] = '';
const errorType = ref<FormErrorType[]>(['message']);
const labelPosition = ref<'left' | 'top'>('left');
const setErrorType = (value: string) => {
errorType.value = [value as FormErrorType];
};
</script>
<style scoped>
.btn-wrap {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-top: 10px;
}
</style>API
Props
ux-form
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
customStyle | Custom root element style | string | UTSJSONObject | - | - |
customClass | Custom root element style class | string | '' | - |
model | Form data object | UTSJSONObject | - | - |
rules | Validation rules | FormRules | - | - |
errorType | Error feedback type | FormErrorType[] | - | - |
borderBottom | Whether to show the bottom border | boolean | true | - |
labelPosition | Label position | FormLabelPosition | 'left' | - |
labelWidth | Label width | string | number | 45 | - |
labelAlign | Label text alignment | string | 'left' | - |
labelStyle | Label style | UTSJSONObject | - | - |
size | Component size | string | 'default' | - |
ux-form-item
| Property | Description | Type | Default | Version |
|---|---|---|---|---|
customStyle | Custom root element style | string | UTSJSONObject | - | - |
customClass | Custom root element style class | string | '' | - |
label | Label text | string | '' | - |
prop | Field name bound in model | string | '' | - |
borderBottom | Whether to show the field's bottom border | string | boolean | '' | - |
labelPosition | Label position | string | '' | - |
labelWidth | Label width | string | number | '' | - |
labelStyle | Label style | UTSJSONObject | - | - |
labelAlign | Label text alignment | string | '' | - |
rightIcon | Right icon | string | '' | - |
leftIcon | Left icon | string | '' | - |
leftIconPrefix | Custom prefix for the left icon | string | 'uicon' | - |
rightIconPrefix | Custom prefix for the right icon | string | 'uicon' | - |
leftIconStyle | Style of the left icon | UTSJSONObject | - | - |
rightIconStyle | Style of the right icon | UTSJSONObject | - | - |
required | Whether to show the required asterisk | boolean | false | - |
size | Size of components inside the field | string | '' | - |
Events
None of the components on this page emits events.
Slots
ux-form
| Slot | Description | Version |
|---|---|---|
default | Form content; place ux-form-items here | - |
ux-form-item
| Slot | Description | Version |
|---|---|---|
leftIcon | Custom left icon | - |
label | Custom label content | - |
default | Field content; place input components (e.g. ux-input) here | - |
rightIcon | Custom right icon | - |
right | Custom right content | - |
Methods
Call them on the ux-form instance obtained via ref:
| Method | Description | Params | Returns |
|---|---|---|---|
validate | Validate all registered fields, running every rule of each field | callback?: (valid: boolean, errorArr: ErrorItem[]) => void | Promise<boolean>, true means all passed |
resetFields | Reset all fields to their initial values and clear error messages | - | - |
setRules | Replace the validation rules dynamically | rules: FormRules | - |
Notes
propis required for validation and reset: aux-form-itemwithoutpropis not registered to the form, sovalidate()andresetFields()skip it. Nested paths such asa.bare supported.requiredonly shows the red asterisk; the actual required check must be configured inruleswithrequired: true. The two do not substitute for each other.- When a rule runs is decided by its
trigger(blur/change): atrigger: 'change'rule does not fire on blur, and vice versa. Callingvalidate()as a whole ignorestriggerand runs all rules of that field. error-typeis an array, so several feedbacks can be enabled at once (default['message', 'toast']). Once the array containsnone, all feedbacks (including message / border) are turned off.toastonly shows the first error of the first failing field.resetFields()restores fields to the initial values captured when the component mounted (nested paths included), rather than clearing them to''.- When
size/label-position/label-width/label-align/border-bottomare not set on aux-form-item, they are inherited fromux-form;border-bottomdefaults totrueonux-form. - When
labelis an empty string, the label area width becomesauto(label-widthno longer applies).