Skip to content

Form ​

17:06

Description ​

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 ​

PlatformSupport
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
vue
<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
vue
<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 ​

PropertyDescriptionTypeDefaultVersion
customStyleCustom root element stylestring | UTSJSONObject--
customClassCustom root element style classstring''-
modelForm data objectUTSJSONObject--
rulesValidation rulesFormRules--
errorTypeError feedback typeFormErrorType[]--
borderBottomWhether to show the bottom borderbooleantrue-
labelPositionLabel positionFormLabelPosition'left'-
labelWidthLabel widthstring | number45-
labelAlignLabel text alignmentstring'left'-
labelStyleLabel styleUTSJSONObject--
sizeComponent sizestring'default'-

ux-form-item ​

PropertyDescriptionTypeDefaultVersion
customStyleCustom root element stylestring | UTSJSONObject--
customClassCustom root element style classstring''-
labelLabel textstring''-
propField name bound in modelstring''-
borderBottomWhether to show the field's bottom borderstring | boolean''-
labelPositionLabel positionstring''-
labelWidthLabel widthstring | number''-
labelStyleLabel styleUTSJSONObject--
labelAlignLabel text alignmentstring''-
rightIconRight iconstring''-
leftIconLeft iconstring''-
leftIconPrefixCustom prefix for the left iconstring'uicon'-
rightIconPrefixCustom prefix for the right iconstring'uicon'-
leftIconStyleStyle of the left iconUTSJSONObject--
rightIconStyleStyle of the right iconUTSJSONObject--
requiredWhether to show the required asteriskbooleanfalse-
sizeSize of components inside the fieldstring''-

Events ​

None of the components on this page emits events.

Slots ​

ux-form ​

SlotDescriptionVersion
defaultForm content; place ux-form-items here-

ux-form-item ​

SlotDescriptionVersion
leftIconCustom left icon-
labelCustom label content-
defaultField content; place input components (e.g. ux-input) here-
rightIconCustom right icon-
rightCustom right content-

Methods ​

Call them on the ux-form instance obtained via ref:

MethodDescriptionParamsReturns
validateValidate all registered fields, running every rule of each fieldcallback?: (valid: boolean, errorArr: ErrorItem[]) => voidPromise<boolean>, true means all passed
resetFieldsReset all fields to their initial values and clear error messages--
setRulesReplace the validation rules dynamicallyrules: FormRules-

Notes ​

  1. prop is required for validation and reset: a ux-form-item without prop is not registered to the form, so validate() and resetFields() skip it. Nested paths such as a.b are supported.
  2. required only shows the red asterisk; the actual required check must be configured in rules with required: true. The two do not substitute for each other.
  3. When a rule runs is decided by its trigger (blur / change): a trigger: 'change' rule does not fire on blur, and vice versa. Calling validate() as a whole ignores trigger and runs all rules of that field.
  4. error-type is an array, so several feedbacks can be enabled at once (default ['message', 'toast']). Once the array contains none, all feedbacks (including message / border) are turned off. toast only shows the first error of the first failing field.
  5. resetFields() restores fields to the initial values captured when the component mounted (nested paths included), rather than clearing them to ''.
  6. When size / label-position / label-width / label-align / border-bottom are not set on a ux-form-item, they are inherited from ux-form; border-bottom defaults to true on ux-form.
  7. When label is an empty string, the label area width becomes auto (label-width no longer applies).