mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(Form): add getValidationStatus method (#10620)
This commit is contained in:
parent
df024f1c6e
commit
3829a1e745
@ -59,6 +59,7 @@ import type {
|
|||||||
FieldFormatTrigger,
|
FieldFormatTrigger,
|
||||||
FieldValidateError,
|
FieldValidateError,
|
||||||
FieldAutosizeConfig,
|
FieldAutosizeConfig,
|
||||||
|
FieldValidationStatus,
|
||||||
FieldValidateTrigger,
|
FieldValidateTrigger,
|
||||||
FieldFormSharedProps,
|
FieldFormSharedProps,
|
||||||
} from './types';
|
} from './types';
|
||||||
@ -135,8 +136,8 @@ export default defineComponent({
|
|||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const id = useId();
|
const id = useId();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
|
status: 'unvalidated' as FieldValidationStatus,
|
||||||
focused: false,
|
focused: false,
|
||||||
validateFailed: false,
|
|
||||||
validateMessage: '',
|
validateMessage: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -181,7 +182,7 @@ export default defineComponent({
|
|||||||
rules.reduce(
|
rules.reduce(
|
||||||
(promise, rule) =>
|
(promise, rule) =>
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
if (state.validateFailed) {
|
if (state.status === 'failed') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +193,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!runSyncRule(value, rule)) {
|
if (!runSyncRule(value, rule)) {
|
||||||
state.validateFailed = true;
|
state.status = 'failed';
|
||||||
state.validateMessage = getRuleMessage(value, rule);
|
state.validateMessage = getRuleMessage(value, rule);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -200,10 +201,10 @@ export default defineComponent({
|
|||||||
if (rule.validator) {
|
if (rule.validator) {
|
||||||
return runRuleValidator(value, rule).then((result) => {
|
return runRuleValidator(value, rule).then((result) => {
|
||||||
if (result && typeof result === 'string') {
|
if (result && typeof result === 'string') {
|
||||||
state.validateFailed = true;
|
state.status = 'failed';
|
||||||
state.validateMessage = result;
|
state.validateMessage = result;
|
||||||
} else if (result === false) {
|
} else if (result === false) {
|
||||||
state.validateFailed = true;
|
state.status = 'failed';
|
||||||
state.validateMessage = getRuleMessage(value, rule);
|
state.validateMessage = getRuleMessage(value, rule);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -213,10 +214,8 @@ export default defineComponent({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const resetValidation = () => {
|
const resetValidation = () => {
|
||||||
if (state.validateFailed) {
|
state.status = 'unvalidated';
|
||||||
state.validateFailed = false;
|
|
||||||
state.validateMessage = '';
|
state.validateMessage = '';
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const validate = (rules = props.rules) =>
|
const validate = (rules = props.rules) =>
|
||||||
@ -224,12 +223,13 @@ export default defineComponent({
|
|||||||
resetValidation();
|
resetValidation();
|
||||||
if (rules) {
|
if (rules) {
|
||||||
runRules(rules).then(() => {
|
runRules(rules).then(() => {
|
||||||
if (state.validateFailed) {
|
if (state.status === 'failed') {
|
||||||
resolve({
|
resolve({
|
||||||
name: props.name,
|
name: props.name,
|
||||||
message: state.validateMessage,
|
message: state.validateMessage,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
state.status = 'passed';
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -352,7 +352,7 @@ export default defineComponent({
|
|||||||
if (typeof props.error === 'boolean') {
|
if (typeof props.error === 'boolean') {
|
||||||
return props.error;
|
return props.error;
|
||||||
}
|
}
|
||||||
if (form && form.props.showError && state.validateFailed) {
|
if (form && form.props.showError && state.status === 'failed') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -384,6 +384,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
const getInputId = () => props.id || `${id}-input`;
|
const getInputId = () => props.id || `${id}-input`;
|
||||||
|
|
||||||
|
const getValidationStatus = () => state.status;
|
||||||
|
|
||||||
const renderInput = () => {
|
const renderInput = () => {
|
||||||
const controlClass = bem('control', [
|
const controlClass = bem('control', [
|
||||||
getProp('inputAlign'),
|
getProp('inputAlign'),
|
||||||
@ -531,6 +533,7 @@ export default defineComponent({
|
|||||||
validate,
|
validate,
|
||||||
formValue,
|
formValue,
|
||||||
resetValidation,
|
resetValidation,
|
||||||
|
getValidationStatus,
|
||||||
});
|
});
|
||||||
|
|
||||||
provide(CUSTOM_FIELD_INJECTION_KEY, {
|
provide(CUSTOM_FIELD_INJECTION_KEY, {
|
||||||
|
@ -327,6 +327,7 @@ import type {
|
|||||||
FieldValidateError,
|
FieldValidateError,
|
||||||
FieldAutosizeConfig,
|
FieldAutosizeConfig,
|
||||||
FieldValidateTrigger,
|
FieldValidateTrigger,
|
||||||
|
FieldValidationStatus,
|
||||||
} from 'vant';
|
} from 'vant';
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -346,6 +346,7 @@ import type {
|
|||||||
FieldValidateError,
|
FieldValidateError,
|
||||||
FieldAutosizeConfig,
|
FieldAutosizeConfig,
|
||||||
FieldValidateTrigger,
|
FieldValidateTrigger,
|
||||||
|
FieldValidationStatus,
|
||||||
} from 'vant';
|
} from 'vant';
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ export type {
|
|||||||
FieldValidateError,
|
FieldValidateError,
|
||||||
FieldAutosizeConfig,
|
FieldAutosizeConfig,
|
||||||
FieldValidateTrigger,
|
FieldValidateTrigger,
|
||||||
|
FieldValidationStatus,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
|
@ -66,6 +66,8 @@ export type FieldRule = {
|
|||||||
formatter?: FiledRuleFormatter;
|
formatter?: FiledRuleFormatter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FieldValidationStatus = 'passed' | 'failed' | 'unvalidated';
|
||||||
|
|
||||||
// Shared props of Field and Form
|
// Shared props of Field and Form
|
||||||
export type FieldFormSharedProps =
|
export type FieldFormSharedProps =
|
||||||
| 'colon'
|
| 'colon'
|
||||||
@ -83,6 +85,7 @@ export type FieldExpose = {
|
|||||||
rules?: FieldRule[] | undefined
|
rules?: FieldRule[] | undefined
|
||||||
) => Promise<void | FieldValidateError>;
|
) => Promise<void | FieldValidateError>;
|
||||||
resetValidation: () => void;
|
resetValidation: () => void;
|
||||||
|
getValidationStatus: () => FieldValidationStatus;
|
||||||
/** @private */
|
/** @private */
|
||||||
formValue: ComputedRef<unknown>;
|
formValue: ComputedRef<unknown>;
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,7 @@ import type {
|
|||||||
FieldTextAlign,
|
FieldTextAlign,
|
||||||
FieldValidateError,
|
FieldValidateError,
|
||||||
FieldValidateTrigger,
|
FieldValidateTrigger,
|
||||||
|
FieldValidationStatus,
|
||||||
} from '../field/types';
|
} from '../field/types';
|
||||||
import type { FormExpose } from './types';
|
import type { FormExpose } from './types';
|
||||||
|
|
||||||
@ -141,6 +142,12 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getValidationStatus = () =>
|
||||||
|
children.reduce<Record<string, FieldValidationStatus>>((form, field) => {
|
||||||
|
form[field.name] = field.getValidationStatus();
|
||||||
|
return form;
|
||||||
|
}, {});
|
||||||
|
|
||||||
const scrollToField = (
|
const scrollToField = (
|
||||||
name: string,
|
name: string,
|
||||||
options?: boolean | ScrollIntoViewOptions
|
options?: boolean | ScrollIntoViewOptions
|
||||||
@ -186,6 +193,7 @@ export default defineComponent({
|
|||||||
getValues,
|
getValues,
|
||||||
scrollToField,
|
scrollToField,
|
||||||
resetValidation,
|
resetValidation,
|
||||||
|
getValidationStatus,
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
|
@ -540,9 +540,10 @@ Use [ref](https://v3.vuejs.org/guide/component-template-refs.html) to get Form i
|
|||||||
| Name | Description | Attribute | Return value |
|
| Name | Description | Attribute | Return value |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| submit | Submit form | - | - |
|
| submit | Submit form | - | - |
|
||||||
| validate | Validate form | _name?: string \| string[]_ | _Promise_ |
|
|
||||||
| getValues `v3.4.8` | Get current form values | - | _Record<string, unknown>_ |
|
| getValues `v3.4.8` | Get current form values | - | _Record<string, unknown>_ |
|
||||||
|
| validate | Validate form | _name?: string \| string[]_ | _Promise\<void\>_ |
|
||||||
| resetValidation | Reset validation | _name?: string \| string[]_ | - |
|
| resetValidation | Reset validation | _name?: string \| string[]_ | - |
|
||||||
|
| getValidationStatus `v3.5.0` | Get validation status of all fields,status can be `passed`、`failed`、`unvalidated` | - | _Record\<string, FieldValidationStatus\>_ |
|
||||||
| scrollToField | Scroll to field | _name: string, alignToTop: boolean_ | - |
|
| scrollToField | Scroll to field | _name: string, alignToTop: boolean_ | - |
|
||||||
|
|
||||||
### Types
|
### Types
|
||||||
|
@ -578,9 +578,10 @@ export default {
|
|||||||
| 方法名 | 说明 | 参数 | 返回值 |
|
| 方法名 | 说明 | 参数 | 返回值 |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| submit | 提交表单,与点击提交按钮的效果等价 | - | - |
|
| submit | 提交表单,与点击提交按钮的效果等价 | - | - |
|
||||||
| validate | 验证表单,支持传入 `name` 来验证单个或部分表单项 | _name?: string \| string[]_ | _Promise_ |
|
|
||||||
| getValues `v3.4.8` | 获取所有表单项当前的值 | - | _Record<string, unknown>_ |
|
| getValues `v3.4.8` | 获取所有表单项当前的值 | - | _Record<string, unknown>_ |
|
||||||
| resetValidation | 重置表单项的验证提示,支持传入 `name` 来重置单个或部分表单项 | _name?: string \| string[]_ | - |
|
| validate | 验证表单,支持传入一个或多个 `name` 来验证单个或部分表单项,不传入 `name` 时,会验证所有表单项 | _name?: string \| string[]_ | _Promise\<void\>_ |
|
||||||
|
| resetValidation | 重置表单项的验证提示,支持传入一个或多个 `name` 来重置单个或部分表单项,不传入 `name` 时,会重置所有表单项 | _name?: string \| string[]_ | - |
|
||||||
|
| getValidationStatus `v3.5.0` | 获取所有表单项的校验状态,状态包括 `passed`、`failed`、`unvalidated` | - | _Record\<string, FieldValidationStatus\>_ |
|
||||||
| scrollToField | 滚动到对应表单项的位置,默认滚动到顶部,第二个参数传 false 可滚动至底部 | _name: string, alignToTop: boolean_ | - |
|
| scrollToField | 滚动到对应表单项的位置,默认滚动到顶部,第二个参数传 false 可滚动至底部 | _name: string, alignToTop: boolean_ | - |
|
||||||
|
|
||||||
### 类型定义
|
### 类型定义
|
||||||
|
@ -153,3 +153,37 @@ test('getValues method should return all current values', () => {
|
|||||||
|
|
||||||
expect(formRef.value?.getValues()).toEqual({ A: '123', B: '456' });
|
expect(formRef.value?.getValues()).toEqual({ A: '123', B: '456' });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('getValidationStatus method should the status of all fields', async () => {
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const rules = getSimpleRules();
|
||||||
|
mount({
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Form ref={formRef}>
|
||||||
|
<Field name="A" rules={rules.rulesA} modelValue="123" />
|
||||||
|
<Field name="B" rules={rules.rulesB} modelValue="456" />
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(formRef.value?.getValidationStatus()).toEqual({
|
||||||
|
A: 'unvalidated',
|
||||||
|
B: 'unvalidated',
|
||||||
|
});
|
||||||
|
|
||||||
|
await formRef.value?.validate();
|
||||||
|
|
||||||
|
expect(formRef.value?.getValidationStatus()).toEqual({
|
||||||
|
A: 'passed',
|
||||||
|
B: 'passed',
|
||||||
|
});
|
||||||
|
|
||||||
|
formRef.value?.resetValidation();
|
||||||
|
|
||||||
|
expect(formRef.value?.getValidationStatus()).toEqual({
|
||||||
|
A: 'unvalidated',
|
||||||
|
B: 'unvalidated',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import type { ComponentPublicInstance } from 'vue';
|
import type { ComponentPublicInstance } from 'vue';
|
||||||
import type { FormProps } from './Form';
|
import type { FormProps } from './Form';
|
||||||
|
import type { FieldValidationStatus } from '../field';
|
||||||
|
|
||||||
export type FormExpose = {
|
export type FormExpose = {
|
||||||
submit: () => void;
|
submit: () => void;
|
||||||
@ -10,6 +11,7 @@ export type FormExpose = {
|
|||||||
options?: boolean | ScrollIntoViewOptions | undefined
|
options?: boolean | ScrollIntoViewOptions | undefined
|
||||||
) => void;
|
) => void;
|
||||||
resetValidation: (name?: string | string[] | undefined) => void;
|
resetValidation: (name?: string | string[] | undefined) => void;
|
||||||
|
getValidationStatus: () => Record<string, FieldValidationStatus>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FormProvide = {
|
export type FormProvide = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user