diff --git a/docs/api-forms.md b/docs/api-forms.md
index 7cf3cf224..94c728423 100644
--- a/docs/api-forms.md
+++ b/docs/api-forms.md
@@ -25,9 +25,9 @@ By default, the validation will take place `onSubmit`, and `onChange` **after th
##### Props:
-| Name | Description |
-| :-------------: | :----------------------------------------------------------------------------------------------------------------------------: |
-| `onChangeModel` | Like `onChange` but for the whole model. Triggered just after `onChange` but with the next model instead of (key, value) pair. |
+| Name | Description |
+| :-------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
+| `onChangeModel` | Like `onChange` but for the whole model. Triggered just after `onChange` with the next model and information what `{ key, value, previousValue }` caused the change. `previousValue` will be `undefined` if there was no value before. |
**Note:** All `ValidatedQuickForm` props are also accepted and all methods are available.
In other words, that means that `AutoForm` receives all props listed on this page.
diff --git a/packages/uniforms/__tests__/AutoForm.tsx b/packages/uniforms/__tests__/AutoForm.tsx
index 86355ba75..87fa53bb7 100644
--- a/packages/uniforms/__tests__/AutoForm.tsx
+++ b/packages/uniforms/__tests__/AutoForm.tsx
@@ -67,7 +67,10 @@ describe('', () => {
});
it('calls `onChangeModel`', () => {
- const schema = new SimpleSchema({ a: { type: String, optional: true } });
+ const schema = new SimpleSchema({
+ a: { type: String, optional: true },
+ b: { type: String, optional: true },
+ });
const bridge = new SimpleSchema2Bridge({ schema });
render(
@@ -75,11 +78,27 @@ describe('', () => {
,
);
- const input = screen.getByLabelText('A');
- fireEvent.change(input, { target: { value: 'a' } });
+ const inputA = screen.getByLabelText('A');
+ fireEvent.change(inputA, { target: { value: 'a' } });
+ expect(onChangeModel).toHaveBeenLastCalledWith(
+ { a: 'a' },
+ { key: 'a', value: 'a', previousValue: undefined },
+ );
+
+ const inputB = screen.getByLabelText('B');
+ fireEvent.change(inputB, { target: { value: 'b' } });
+ expect(onChangeModel).toHaveBeenLastCalledWith(
+ { a: 'a', b: 'b' },
+ { key: 'b', value: 'b', previousValue: undefined },
+ );
+
+ fireEvent.change(inputB, { target: { value: 'bb' } });
+ expect(onChangeModel).toHaveBeenLastCalledWith(
+ { a: 'a', b: 'bb' },
+ { key: 'b', value: 'bb', previousValue: 'b' },
+ );
- expect(onChangeModel).toHaveBeenCalledTimes(1);
- expect(onChangeModel).toHaveBeenLastCalledWith({ a: 'a' });
+ expect(onChangeModel).toHaveBeenCalledTimes(3);
});
it('updates `changed` and `changedMap`', () => {
diff --git a/packages/uniforms/src/AutoForm.tsx b/packages/uniforms/src/AutoForm.tsx
index 0462b2188..fa03f5209 100644
--- a/packages/uniforms/src/AutoForm.tsx
+++ b/packages/uniforms/src/AutoForm.tsx
@@ -1,4 +1,5 @@
import clone from 'lodash/clone';
+import get from 'lodash/get';
import isEqual from 'lodash/isEqual';
import omit from 'lodash/omit';
import setWith from 'lodash/setWith';
@@ -15,7 +16,10 @@ import { ModelTransformMode, UnknownObject } from './types';
export type AutoFormProps =
ValidatedQuickFormProps & {
- onChangeModel?: (model: Model) => void;
+ onChangeModel?: (
+ model: Model,
+ info: { key: string; value: unknown; previousValue: unknown },
+ ) => void;
};
export type AutoFormState =
@@ -77,12 +81,17 @@ export function Auto(Base: Base) {
}
onChange(key: string, value: unknown) {
+ const previousValue: unknown = get(this.state.model, key);
super.onChange(key, value);
this.setState(
state => ({ model: setWith(clone(state.model), key, value, clone) }),
() => {
if (this.props.onChangeModel) {
- this.props.onChangeModel(this.state.model);
+ this.props.onChangeModel(this.state.model, {
+ key,
+ value,
+ previousValue,
+ });
}
},
);