Merge remote-tracking branch 'baidu/master'

This commit is contained in:
liaoxuezhi 2022-11-13 23:46:24 +08:00
commit a987738a58
4 changed files with 74 additions and 12 deletions

View File

@ -17,6 +17,13 @@ export default function ButtonExamples() {
setIsShow(false);
}, []);
async function handleValidate() {
return new Promise<void>((resolve, reject) => {
// setTimeout(() => reject('error message'), 200);
setTimeout(() => resolve(), 200);
});
}
return (
<div className="wrapper">
<Button onClick={handleClick}>Open</Button>
@ -29,7 +36,7 @@ export default function ButtonExamples() {
onCancel={handleCancel}
>
{({bodyRef}) => (
<Form ref={bodyRef}>
<Form ref={bodyRef} onValidate={handleValidate}>
{({control}) => (
<>
<Controller

View File

@ -3,6 +3,7 @@ import Modal from './Modal';
import Button from './Button';
import Drawer from './Drawer';
import {localeable, LocaleProps, themeable, ThemeProps} from 'amis-core';
import Spinner from './Spinner';
export interface ConfirmBoxProps extends LocaleProps, ThemeProps {
show?: boolean;
@ -56,19 +57,32 @@ export function ConfirmBox({
bodyClassName,
footerClassName
}: ConfirmBoxProps) {
const [loading, setLoading] = React.useState<boolean>();
const [error, setError] = React.useState<string>();
const bodyRef = React.useRef<
{submit: () => Promise<Record<string, any>>} | undefined
>();
const handleConfirm = React.useCallback(async () => {
const ret = beforeConfirm
? await beforeConfirm?.(bodyRef.current)
: await bodyRef.current?.submit?.();
setError('');
setLoading(true);
try {
const ret = beforeConfirm
? await beforeConfirm?.(bodyRef.current)
: await bodyRef.current?.submit?.();
if (ret === false) {
return;
if (ret === false) {
return;
} else if (typeof ret === 'string') {
setError(ret);
return;
}
onConfirm?.(ret);
} catch (e) {
setError(e.message);
} finally {
setLoading(false);
}
onConfirm?.(ret);
}, [onConfirm, beforeConfirm]);
function renderDialog() {
@ -95,6 +109,14 @@ export function ConfirmBox({
</Modal.Body>
{showFooter ?? true ? (
<Modal.Footer className={footerClassName}>
{loading || error ? (
<div className={cx('Dialog-info')}>
<Spinner size="sm" key="info" show={loading} />
{error ? (
<span className={cx('Dialog-error')}>{error}</span>
) : null}
</div>
) : null}
<Button onClick={onCancel}>{__('cancel')}</Button>
<Button onClick={handleConfirm} level="primary">
{__('confirm')}
@ -132,6 +154,14 @@ export function ConfirmBox({
</div>
{showFooter ?? true ? (
<div className={cx('Drawer-footer', footerClassName)}>
{loading || error ? (
<div className={cx('Drawer-info')}>
<Spinner size="sm" key="info" show={loading} />
{error ? (
<span className={cx('Drawer-error')}>{error}</span>
) : null}
</div>
) : null}
<Button onClick={handleConfirm} level="primary">
{__('confirm')}
</Button>

View File

@ -18,6 +18,7 @@ export type FormRef = React.MutableRefObject<
export interface FormProps extends ThemeProps, LocaleProps {
defaultValue?: any;
autoSubmit?: boolean;
onValidate?: (errors: any, values: any) => Promise<void>;
onSubmit?: (value: any) => void;
forwardRef?: FormRef;
children?: (
@ -32,7 +33,7 @@ export function Form(props: FormProps) {
const {classnames: cx, className, autoSubmit} = props;
const methods = useForm({
defaultValues: props.defaultValue,
resolver: useValidationResolver(props.translate)
resolver: useValidationResolver(props.translate, props.onValidate)
});
let onSubmit = React.useRef<(data: any) => void>(
methods.handleSubmit(props.onSubmit || noop)
@ -66,7 +67,7 @@ export function Form(props: FormProps) {
props.onSubmit?.(values);
resolve(values);
},
() => resolve(false)
e => resolve(e.customValidate?.message || false)
)();
})
};

View File

@ -19,7 +19,20 @@ function formatErrors(errors: any) {
return formated;
}
export function useValidationResolver(__ = (str: string) => str) {
export function useValidationResolver(
__ = (str: string) => str,
validate?: (
error: {
[propName: string]: {
rule: string;
msg: string;
}[];
},
values: Record<string, any>,
context: any,
config: any
) => Promise<void>
) {
return React.useCallback<any>(
async (values: any, context: any, config: any) => {
const rules: any = {};
@ -53,12 +66,23 @@ export function useValidationResolver(__ = (str: string) => str) {
}
}
try {
await validate?.(errors, values, context, config);
} catch (e) {
errors.customValidate = [
{
rule: 'custom',
msg: e.message || e
}
];
}
return {
values,
errors: formatErrors(errors)
};
},
[__]
[__, validate]
);
}