Skip to content

Commit

Permalink
Extend onChangeModel
Browse files Browse the repository at this point in the history
  • Loading branch information
kestarumper committed Aug 23, 2024
1 parent 884581a commit 5567491
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 10 deletions.
6 changes: 3 additions & 3 deletions docs/api-forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
29 changes: 24 additions & 5 deletions packages/uniforms/__tests__/AutoForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,38 @@ describe('<AutoForm />', () => {
});

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(
<AutoForm onChangeModel={onChangeModel} schema={bridge}>
<AutoFields />
</AutoForm>,
);

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`', () => {
Expand Down
13 changes: 11 additions & 2 deletions packages/uniforms/src/AutoForm.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -15,7 +16,10 @@ import { ModelTransformMode, UnknownObject } from './types';

export type AutoFormProps<Model extends UnknownObject> =
ValidatedQuickFormProps<Model> & {
onChangeModel?: (model: Model) => void;
onChangeModel?: (
model: Model,
info: { key: string; value: unknown; previousValue: unknown },
) => void;
};

export type AutoFormState<Model extends UnknownObject> =
Expand Down Expand Up @@ -77,12 +81,17 @@ export function Auto<Base extends typeof ValidatedQuickForm>(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,
});
}
},
);
Expand Down

0 comments on commit 5567491

Please sign in to comment.