Skip to content

Commit

Permalink
Merge pull request #169 from jimengio/async-submit
Browse files Browse the repository at this point in the history
fix: 表单提交异步验证失效问题
  • Loading branch information
rebirthO authored Jan 18, 2021
2 parents 54ff746 + c1bb0be commit 4d5ec2a
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 7 deletions.
28 changes: 24 additions & 4 deletions example/forms/async-validation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,20 @@ let formItems: IMesonFieldItem[] = [
required: true,
placeholder: "不能有数字",
asyncValidator: async (x, item, form) => {
await new Promise((resolve, reject) => {
const errInfo: string = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
if (x === "test") {
resolve("duplicate last name");
} else {
resolve();
}
}, 1000);
});

if (errInfo) {
return errInfo;
}

if (x?.match(/\d/)) {
return "should not have digits in name";
}
Expand Down Expand Up @@ -93,11 +102,22 @@ let formItems: IMesonFieldItem[] = [
return {};
},
asyncValidateMultiple: async (form) => {
await new Promise((resolve, reject) => {
const errInfo: Record<string, string> = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
if (form.province === "test") {
resolve({
province: "province does not exist",
});
} else {
resolve();
}
}, 1000);
});

if (errInfo) {
return errInfo;
}

let ret = {
province: undefined,
city: undefined,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jimengio/meson-form",
"version": "0.4.22-legacy0",
"version": "0.5.2-legacy2",
"description": "",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
Expand Down
28 changes: 26 additions & 2 deletions src/hook/meson-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState, useRef } from "react";
import { useImmer } from "use-immer";
import { IMesonFieldItem, IMesonFieldItemHasValue, FuncMesonModifyForm, IMesonCustomMultipleField, IMesonErrors, FieldValues, FieldName } from "../model/types";
import { validateItem, hasErrorInObject } from "../util/validation";
import { traverseItems, traverseItemsReachCustomMultiple } from "../util/render";
import { traverseItems, traverseItemsReachCustomMultiple, asyncCustomeValidateItems } from "../util/render";
import produce, { Draft } from "immer";
import { union, isFunction, isEmpty } from "lodash-es";
import { isEmptyErrorsObject } from "../util/data";
Expand All @@ -25,7 +25,7 @@ export let useMesonCore = <T extends FieldValues, TransferData>(props: {
let [errors, updateErrors] = useImmer<IMesonErrors<T>>({});
let modifiedState = useRef(false);

let onCheckSubmitWithValue = (passedForm?: T, options?: ICheckSubmitOptions<T, TransferData>) => {
let onCheckSubmitWithValue = async (passedForm?: T, options?: ICheckSubmitOptions<T, TransferData>) => {
let latestForm = passedForm;
let currentErrors: IMesonErrors<T> = {};
let hasErrors = false;
Expand All @@ -50,6 +50,30 @@ export let useMesonCore = <T extends FieldValues, TransferData>(props: {
}
});

await asyncCustomeValidateItems(props.items, latestForm, async (i) => {
switch (i.type) {
case "custom-multiple":
const multItem = i as IMesonCustomMultipleField<T>;
if (isFunction(multItem.asyncValidateMultiple)) {
let results = await multItem.asyncValidateMultiple(latestForm, multItem);
if (hasErrorInObject(results)) {
Object.assign(currentErrors, results);
hasErrors = true;
}
}
break;
default:
const item = i as IMesonFieldItemHasValue<T>;
if (isFunction(item.asyncValidator)) {
let result = await item.asyncValidator(latestForm[item.name], item, latestForm);
if (result) {
currentErrors[item.name] = result;
hasErrors = true;
}
}
}
});

updateErrors((draft) => {
return currentErrors;
});
Expand Down
20 changes: 20 additions & 0 deletions src/util/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,23 @@ export function traverseItemsReachCustomMultiple<T extends FieldValues>(xs: IMes
}
});
}

export async function asyncCustomeValidateItems<T extends FieldValues>(xs: IMesonFieldItem<T>[], form: T, method: (x: IMesonFieldItem<T>) => void) {
const xsPromises = xs.map(async (x) => {
if (x.shouldHide != null && x.shouldHide(form)) {
return null;
}

switch (x.type) {
case "decorative":
return;
case "nested":
case "group":
await asyncCustomeValidateItems(x.children, form, method);
default:
await method(x);
}
});

await Promise.all(xsPromises);
}

0 comments on commit 4d5ec2a

Please sign in to comment.