Skip to content

Commit

Permalink
fix(form): validation pending
Browse files Browse the repository at this point in the history
  • Loading branch information
07akioni committed Jan 8, 2024
1 parent 644185f commit 3968616
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 49 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Fixes

- Click clear button on components with popup may trigger reopen behaviors.
- Fix `n-form`'s `validate` returned `Promise` may not `resolve`.

### Features

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Fixes

- 点击具有弹出菜单的组件的清空按钮时,可能会触发菜单的重复出现
- `n-form``validate` 方法返回的 `Promise` 可能不会 `resolve`

### Features

Expand Down
4 changes: 2 additions & 2 deletions src/form/demos/enUS/index.demo-entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ Accept all props from FormItem & [GridItem](grid#GridItem-Props)

| Name | Type | Description | Version |
| --- | --- | --- | --- |
| validate | `(validateCallback?: (errors: Array<FormValidationError> \| undefined, extra: { warnings: Array<FormValidationError> \| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<void>` | Validate the form. The rejection value type of returned promise is `Array<FormValidationError>`. | `warnings` `2.37.0` |
| validate | `(validateCallback?: (errors: Array<FormValidationError> \| undefined, extra: { warnings: Array<FormValidationError> \| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<{ warnings: Array<FormValidationError> \| undefined }>` | Validate the form. The rejection value type of returned promise is `Array<FormValidationError>`. | `warnings` `2.37.1` |
| restoreValidation | `() => void` | Restore validate. | |

### FormItem, FormItemGi Methods

| Name | Type | Description | Version |
| --- | --- | --- | --- |
| validate | `(options: { trigger?: string, callback?: (errors: Array<FormValidationError> \| undefined, extra: { warnings: Array<FormValidationError> \| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<void>` | Validate the form item. The rejection value type of returned promise is `Array<FormValidationError>`. If trigger is not set, all rules of the item will be applied. `shouldRuleBeApplied` can filter rules after they are filtered by the trigger. | `warnings` `2.37.0` |
| validate | `(options: { trigger?: string, callback?: (errors: FormValidationError \| undefined, extra: { warnings: FormValidationError \| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<{ warnings: FormValidationError \| undefined }>` | Validate the form item. The rejection value type of returned promise is `FormValidationError`. If trigger is not set, all rules of the item will be applied. `shouldRuleBeApplied` can filter rules after they are filtered by the trigger. | `warnings` `2.37.1` |
| restoreValidation | `() => void` | Restore validate. | |

To find out more about AsyncValidatorOptions, see <n-a href="https://github.com/yiminghe/async-validator" target="_blank">async-validator</n-a>.
Expand Down
4 changes: 2 additions & 2 deletions src/form/demos/zhCN/index.demo-entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,14 @@ dynamic.vue

| 名称 | 类型 | 说明 | 版本 |
| --- | --- | --- | --- |
| validate | `(validateCallback?: (errors: Array<FormValidationError> \| undefined, extra: { warnings: Array<FormValidationError> \| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<void>` | 验证表单,Promise rejection 的返回值类型是 `Array<FormValidationError>` | `warnings` `2.37.0` |
| validate | `(validateCallback?: (errors: Array<FormValidationError> \| undefined, extra: { warnings: Array<FormValidationError> \| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<{ warnings: Array<FormValidationError> \| undefined }>` | 验证表单,Promise rejection 的返回值类型是 `Array<FormValidationError>` | `warnings` `2.37.1` |
| restoreValidation | `() => void` | 还原到未校验的状态 | |

### FormItem, FormItemGi Methods

| 名称 | 类型 | 说明 | 版本 |
| --- | --- | --- | --- |
| validate | `(options: { trigger?: string, callback?: (errors: Array<FormValidationError> \| undefined, extra: { warnings: Array<FormValidationError> \| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<void>` | 验证表项,Promise rejection 的返回值类型是 `Array<FormValidationError>`。如果不设定 `trigger`,这一个表项全部的规则都会被使用。`shouldRuleBeApplied` 可以用来进一步过滤已经经过 `trigger` 筛选的规则 | `warnings` `2.37.0` |
| validate | `(options: { trigger?: string, callback?: (errors: FormValidationError \| undefined, extra: { warnings: FormValidationError \| undefined }) => void, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<{ warnings: FormValidationError \| undefined }>` | 验证表项,Promise rejection 的返回值类型是 `FormValidationError`。如果不设定 `trigger`,这一个表项全部的规则都会被使用。`shouldRuleBeApplied` 可以用来进一步过滤已经经过 `trigger` 筛选的规则 | `warnings` `2.37.1` |
| restoreValidation | `() => void` | 还原到未校验的状态 | |

关于 AsyncValidatorOptions,参考 <n-a href="https://github.com/yiminghe/async-validator" target="_blank">async-validator</n-a>。
Expand Down
75 changes: 40 additions & 35 deletions src/form/src/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,44 +90,49 @@ export default defineComponent({
async function validate (
validateCallback?: FormValidateCallback,
shouldRuleBeApplied: ShouldRuleBeApplied = () => true
): Promise<void> {
await new Promise<void>((resolve, reject) => {
const formItemValidationPromises: Array<
Promise<FormItemInternalValidateResult>
> = []
for (const key of keysOf(formItems)) {
const formItemInstances = formItems[key]
for (const formItemInstance of formItemInstances) {
if (formItemInstance.path) {
formItemValidationPromises.push(
formItemInstance.internalValidate(null, shouldRuleBeApplied)
)
): Promise<{ warnings: ValidateError[][] | undefined }> {
return await new Promise<{ warnings: ValidateError[][] | undefined }>(
(resolve, reject) => {
const formItemValidationPromises: Array<
Promise<FormItemInternalValidateResult>
> = []
for (const key of keysOf(formItems)) {
const formItemInstances = formItems[key]
for (const formItemInstance of formItemInstances) {
if (formItemInstance.path) {
formItemValidationPromises.push(
formItemInstance.internalValidate(null, shouldRuleBeApplied)
)
}
}
}
}
void Promise.all(formItemValidationPromises).then((results) => {
const formInvalid = results.some((result) => !result.valid)

const errors = results
.filter((result) => result.errors?.length)
.map((result) => result.errors)
const warnings = results
.filter((result) => result.warnings?.length)
.map((result) => result.warnings)
if (validateCallback) {
validateCallback(
errors?.length ? (errors as ValidateError[][]) : undefined,
{
warnings: warnings?.length
? (warnings as ValidateError[][])
: undefined
void Promise.all(formItemValidationPromises).then((results) => {
const formInvalid = results.some((result) => !result.valid)
const errors: ValidateError[][] = []
const warnings: ValidateError[][] = []
results.forEach((result) => {
if (result.errors?.length) {
errors.push(result.errors)
}
)
} else {
formInvalid ? reject(errors) : resolve()
}
})
})
if (result.warnings?.length) {
warnings.push(result.warnings)
}
})
if (validateCallback) {
validateCallback(errors.length ? errors : undefined, {
warnings: warnings.length ? warnings : undefined
})
}
if (formInvalid) {
reject(errors.length ? errors : undefined)
} else {
resolve({
warnings: warnings.length ? warnings : undefined
})
}
})
}
)
}
function restoreValidation (): void {
for (const key of keysOf(formItems)) {
Expand Down
18 changes: 13 additions & 5 deletions src/form/src/FormItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,21 @@ export default defineComponent({
}
// Resolve : ()
// Reject : (errors: AsyncValidator.ValidateError[])
async function validate (options: FormItemValidateOptions): Promise<void>
async function validate (options: FormItemValidateOptions): Promise<{
warnings: ValidateError[] | undefined
}>
async function validate (
trigger?: string | null,
callback?: ValidateCallback
): Promise<void>
): Promise<{
warnings: ValidateError[] | undefined
}>
async function validate (
options?: string | null | FormItemValidateOptions,
callback?: ValidateCallback
): Promise<void> {
): Promise<{
warnings: ValidateError[] | undefined
}> {
/** the following code is for compatibility */
let trigger: ValidationTrigger | string | undefined
let validateCallback: ValidateCallback | undefined
Expand All @@ -232,7 +238,9 @@ export default defineComponent({
shouldRuleBeApplied = options.shouldRuleBeApplied
asyncValidatorOptions = options.options
}
await new Promise<void>((resolve, reject) => {
return await new Promise<{
warnings: ValidateError[] | undefined
}>((resolve, reject) => {
void internalValidate(
trigger,
shouldRuleBeApplied,
Expand All @@ -242,7 +250,7 @@ export default defineComponent({
if (validateCallback) {
validateCallback(undefined, { warnings })
}
resolve()
resolve({ warnings })
} else {
if (validateCallback) {
validateCallback(errors, { warnings })
Expand Down
15 changes: 10 additions & 5 deletions src/form/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,13 @@ export type FormItemInternalValidate = (
options?: ValidateOption
) => Promise<FormItemInternalValidateResult>

export type FormItemValidate = ((
options: FormItemValidateOptions
) => Promise<void>) &
((trigger?: string, callback?: ValidateCallback) => Promise<void>)
export type FormItemValidate = ((options: FormItemValidateOptions) => Promise<{
warnings: ValidateError[] | undefined
}>) &
((
trigger?: string,
callback?: ValidateCallback
) => Promise<{ warnings: ValidateError[] | undefined }>)

export interface FormItemInst {
validate: FormItemValidate
Expand Down Expand Up @@ -100,7 +103,9 @@ export type FormValidateCallback = (
export type FormValidate = (
callback?: FormValidateCallback,
shouldRuleBeApplied?: ShouldRuleBeApplied
) => Promise<void>
) => Promise<{
warnings: ValidateError[][] | undefined
}>

export type FormValidationError = ValidateError[]

Expand Down

0 comments on commit 3968616

Please sign in to comment.