Skip to content

Commit

Permalink
feat(form): 新增 onValuesChange 事件 (#121)
Browse files Browse the repository at this point in the history
  • Loading branch information
honkinglin authored Dec 30, 2021
1 parent da772a0 commit 1b2b349
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 28 deletions.
33 changes: 21 additions & 12 deletions src/form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import isNil from 'lodash/isNil';
import isFunction from 'lodash/isFunction';
import flatten from 'lodash/flatten';
import useConfig from '../_util/useConfig';
import noop from '../_util/noop';
import forwardRefWithStatics from '../_util/forwardRefWithStatics';
import { TdFormProps, FormValidateResult } from './type';
import { TdFormProps, FormInstance, Result } from './type';
import { StyledProps } from '../common';
import FormContext from './FormContext';
import FormItem from './FormItem';
Expand All @@ -15,8 +16,6 @@ export interface FormProps extends TdFormProps, StyledProps {
children?: React.ReactNode;
}

export type Result = FormValidateResult<FormData>;

const Form = forwardRefWithStatics(
(props: FormProps, ref) => {
const {
Expand All @@ -36,6 +35,7 @@ const Form = forwardRefWithStatics(
children,
onSubmit,
onReset,
onValuesChange = noop,
} = props;
const { classPrefix } = useConfig();
const formClass = classNames(className, `${classPrefix}-form`, {
Expand Down Expand Up @@ -150,15 +150,23 @@ const Form = forwardRefWithStatics(
});
}

useImperativeHandle(ref, (): any => ({
submit: submitHandler,
reset: resetHandler,
getFieldValue,
setFieldsValue,
setFields,
validate,
getAllFieldsValue,
}));
useImperativeHandle(
ref,
(): FormInstance => ({
submit: submitHandler,
reset: resetHandler,
getFieldValue,
setFieldsValue,
setFields,
validate,
getAllFieldsValue,
}),
);

function onFormItemValueChange(changedValue: Record<string, unknown>) {
const allFileds = getAllFieldsValue();
onValuesChange(changedValue, allFileds);
}

return (
<FormContext.Provider
Expand All @@ -174,6 +182,7 @@ const Form = forwardRefWithStatics(
scrollToFirstError,
resetType,
rules,
onFormItemValueChange,
}}
>
<form className={formClass} style={style} onSubmit={submitHandler} onReset={resetHandler} ref={formRef}>
Expand Down
2 changes: 2 additions & 0 deletions src/form/FormContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const FormContext = React.createContext<{
showErrorMessage: TdFormProps['showErrorMessage'];
resetType: TdFormProps['resetType'];
rules: TdFormProps['rules'];
onFormItemValueChange: (changedValue: Record<string, unknown>) => void;
}>({
labelWidth: 'calc(1 / 12 * 100%)',
labelAlign: 'right',
Expand All @@ -25,6 +26,7 @@ const FormContext = React.createContext<{
resetType: 'empty',
rules: undefined,
statusIcon: false,
onFormItemValueChange: undefined,
});

export const useFormContext = () => React.useContext(FormContext);
Expand Down
11 changes: 10 additions & 1 deletion src/form/FormItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const FormItem = forwardRef<HTMLDivElement, FormItemProps>((props, ref) => {
resetType,
rules: rulesFromContext,
statusIcon: statusIconFromContext,
onFormItemValueChange,
} = useFormContext();

const [errorList, setErrorList] = useState([]);
Expand All @@ -62,6 +63,7 @@ const FormItem = forwardRef<HTMLDivElement, FormItemProps>((props, ref) => {

const innerFormItemsRef = useRef([]);
const shouldValidate = useRef(null);
const isMounted = useRef(false);

const innerRules: FormRule[] = (rulesFromContext && rulesFromContext[name]) || rulesFromProp || [];
const innerLabelWidth = isNil(labelWidth) ? labelWidthFromContext : labelWidth;
Expand Down Expand Up @@ -185,8 +187,15 @@ const FormItem = forwardRef<HTMLDivElement, FormItemProps>((props, ref) => {
}

useEffect(() => {
// value change event
if (isMounted.current) {
if (!name) console.warn('FormItem prop name is required.');
name && onFormItemValueChange({ [name]: formValue });
}

// 首次渲染不触发校验 后续判断是否检验也通过此字段控制
if (!shouldValidate.current) {
if (!shouldValidate.current || !isMounted.current) {
isMounted.current = true;
shouldValidate.current = true;
return;
}
Expand Down
15 changes: 8 additions & 7 deletions src/form/form.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ size | String | medium | 表单尺寸。可选项:medium/large | N
statusIcon | TNode | undefined | 校验状态图标。TS 类型:`boolean | TNode<TdFormItemProps>`[通用类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/common.ts) | N
onReset | Function | | 表单重置时触发。`(context: { e?: FormResetEvent }) => {}` | N
onSubmit | Function | | 表单提交时触发。其中 context.validateResult 表示校验结果,context .firstError 表示校验不通过的第一个规则提醒。context.validateResult 值为 true 表示校验通过;如果校验不通过,context.validateResult 值为校验结果列表。[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/form/type.ts)`(context: SubmitContext<FormData>) => {}` | N
onValuesChange | Function | | 字段值更新时触发的回调事件。`(changedValues: Record<string, unknown>, allValues: Record<string, unknown>) => {}` | N

### FormItem Props

Expand Down Expand Up @@ -62,10 +63,10 @@ validator | Function | - | 自定义校验规则。TS 类型:`CustomValidator`

名称 | 类型 | 默认值 | 说明 | 必传
-- | -- | -- | -- | --
getAllFieldsValue | Function | - | 获取全部表单数据。TS 类型:`() => Record<string, unknown>` | N
getFieldValue | Function | - | 获取单个字段值。TS 类型:`(field: string) => unknown` | N
reset | Function | - | 重置表单,与点击 reset 按钮效果相同。TS 类型:`() => void` | N
setFields | Function | - | 设置多组字段状态。TS 类型:`(fields: FieldData[]) => void`[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/form/type.ts) | N
setFieldsValue | Function | - | 设置表单字段值。TS 类型:`(field: FieldOption) => void`[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/form/type.ts) | N
submit | Function | - | 提交表单,与点击 submit 按钮效果相同。TS 类型:`() => void` | N
validate | Function | - | 校验。TS 类型:`() => ValidateResult<{ [key: string]: boolean | ErrorList }>` | N
getAllFieldsValue | Function | - | 必需。获取全部表单数据。TS 类型:`() => Record<string, unknown>` | Y
getFieldValue | Function | - | 必需。获取单个字段值。TS 类型:`(field: string) => unknown` | Y
reset | Function | - | 必需。重置表单,与点击 reset 按钮效果相同。TS 类型:`(e?: FormEvent<HTMLFormElement>) => void` | Y
setFields | Function | - | 必需。设置多组字段状态。TS 类型:`(fields: FieldData[]) => void`[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/form/type.ts) | Y
setFieldsValue | Function | - | 必需。设置表单字段值。TS 类型:`(field: FieldOption) => void`[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/form/type.ts) | Y
submit | Function | - | 必需。提交表单,与点击 submit 按钮效果相同。TS 类型:`(e?: FormEvent<HTMLFormElement>) => void` | Y
validate | Function | - | 必需。校验。TS 类型:`() => Promise<Result>`[详细类型定义](https://github.com/Tencent/tdesign-react/blob/develop/src/form/type.ts) | Y
23 changes: 15 additions & 8 deletions src/form/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

/**
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* updated at 2021-12-27 17:08:43
* updated at 2021-12-29 16:18:25
* */

import { IsEmailOptions } from 'validator/es/lib/isEmail';
import { IsURLOptions } from 'validator/es/lib/isURL';
import { TNode, FormResetEvent, FormSubmitEvent } from '../common';
import { FormEvent } from 'react';

export interface TdFormProps<FormData extends Data = Data> {
/**
Expand Down Expand Up @@ -74,6 +75,10 @@ export interface TdFormProps<FormData extends Data = Data> {
* 表单提交时触发。其中 context.validateResult 表示校验结果,context .firstError 表示校验不通过的第一个规则提醒。context.validateResult 值为 true 表示校验通过;如果校验不通过,context.validateResult 值为校验结果列表
*/
onSubmit?: (context: SubmitContext<FormData>) => void;
/**
* 字段值更新时触发的回调事件
*/
onValuesChange?: (changedValues: Record<string, unknown>, allValues: Record<string, unknown>) => void;
}

export interface TdFormItemProps {
Expand Down Expand Up @@ -207,31 +212,31 @@ export interface FormInstance {
/**
* 获取全部表单数据
*/
getAllFieldsValue?: () => Record<string, unknown>;
getAllFieldsValue: () => Record<string, unknown>;
/**
* 获取单个字段值
*/
getFieldValue?: (field: string) => unknown;
getFieldValue: (field: string) => unknown;
/**
* 重置表单,与点击 reset 按钮效果相同
*/
reset?: () => void;
reset: (e?: FormEvent<HTMLFormElement>) => void;
/**
* 设置多组字段状态
*/
setFields?: (fields: FieldData[]) => void;
setFields: (fields: FieldData[]) => void;
/**
* 设置表单字段值
*/
setFieldsValue?: (field: FieldOption) => void;
setFieldsValue: (field: FieldOption) => void;
/**
* 提交表单,与点击 submit 按钮效果相同
*/
submit?: () => void;
submit: (e?: FormEvent<HTMLFormElement>) => void;
/**
* 校验
*/
validate?: () => ValidateResult<{ [key: string]: boolean | ErrorList }>;
validate: () => Promise<Result>;
}

export interface SubmitContext<T extends Data = Data> {
Expand Down Expand Up @@ -283,3 +288,5 @@ export interface FieldData {
}

export type FieldOption = Record<string, unknown>;

export type Result = FormValidateResult<FormData>;

0 comments on commit 1b2b349

Please sign in to comment.