feat: amis-ui>form 支持受控模式

This commit is contained in:
2betop 2022-12-08 20:30:50 +08:00
parent a7600f2bb9
commit f9798d1501
3 changed files with 88 additions and 2 deletions

View File

@ -25,6 +25,11 @@ const pages: TreeArray = [
{
label: '表单',
children: [
{
label: '受控表单',
path: '/form/controlled-form',
component: React.lazy(() => import('./form/ControlledForm'))
},
{
label: 'InputTable',
path: '/form/input-table',

View File

@ -0,0 +1,63 @@
import React from 'react';
import {Button, Combo, Form, Controller, InputBox} from 'amis-ui';
export default function ControlledFormExamples() {
const [formValues, setFormValues] = React.useState<{
a: any;
b: any;
}>({a: 1, b: 2});
const handleSubmit = React.useCallback((data: any) => {
console.log('submit', data);
}, []);
const handleChange = React.useCallback((values: any) => {
setFormValues(values);
}, []);
const handleRandomChange = React.useCallback(() => {
setFormValues({
a: Math.random(),
b: Math.random()
});
}, []);
return (
<div className="wrapper">
<Form value={formValues} onSubmit={handleSubmit} onChange={handleChange}>
{({control, onSubmit}) => {
return (
<>
<Controller
name="a"
control={control}
isRequired
render={({field, fieldState}) => (
<InputBox
{...field}
placeholder="Key"
hasError={!!fieldState.error}
disabled={false}
/>
)}
/>
<Controller
name="b"
control={control}
isRequired
render={({field, fieldState}) => (
<InputBox
{...field}
placeholder="Title"
hasError={!!fieldState.error}
disabled={false}
/>
)}
/>
<Button onClick={handleRandomChange}></Button>
<Button onClick={onSubmit}>Submit</Button>
</>
);
}}
</Form>
</div>
);
}

View File

@ -7,6 +7,7 @@ import {useForm, UseFormReturn, FormProvider} from 'react-hook-form';
import {useValidationResolver} from '../hooks/use-validation-resolver';
import {localeable, LocaleProps} from 'amis-core';
import debounce from 'lodash/debounce';
import {isObjectShallowModified} from 'amis-core';
export type FormRef = React.MutableRefObject<
| {
@ -17,8 +18,10 @@ export type FormRef = React.MutableRefObject<
export interface FormProps extends ThemeProps, LocaleProps {
defaultValue?: any;
value?: any;
autoSubmit?: boolean;
onValidate?: (errors: any, values: any) => Promise<void>;
onChange?: (value: any) => void;
onSubmit?: (value: any) => void;
forwardRef?: FormRef;
children?: (
@ -30,9 +33,9 @@ export interface FormProps extends ThemeProps, LocaleProps {
}
export function Form(props: FormProps) {
const {classnames: cx, className, autoSubmit} = props;
const {classnames: cx, className, autoSubmit, value, onChange} = props;
const methods = useForm({
defaultValues: props.defaultValue,
defaultValues: props.value ?? props.defaultValue,
resolver: useValidationResolver(props.translate, props.onValidate)
});
let onSubmit = React.useRef<(data: any) => void>(
@ -55,6 +58,21 @@ export function Form(props: FormProps) {
};
}, []);
}
React.useEffect(() => {
if (value && isObjectShallowModified(value, methods.getValues())) {
Object.keys(value).forEach(key => {
methods.setValue(key, value[key]);
});
}
}, [value]);
if (onChange) {
React.useEffect(() => {
const subscriber = methods.watch(value => {
onChange(value);
});
return () => subscriber.unsubscribe();
}, [onChange]);
}
React.useEffect(() => {
if (props.forwardRef) {