Skip to content

Commit 85ebdd1

Browse files
authored
Merge pull request #876 from rvsia/setFormValidting
fix(manager): set form.validating to true when a field is being validated
2 parents f250e65 + c3f6c9e commit 85ebdd1

File tree

3 files changed

+55
-4
lines changed

3 files changed

+55
-4
lines changed

packages/form-state-manager/src/tests/utils/manager-api.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,39 @@ describe('managerApi', () => {
14991499
});
15001500
});
15011501
});
1502+
1503+
it('should set form.validating when fields are validating', async (done) => {
1504+
expect.assertions(8);
1505+
jest.useFakeTimers();
1506+
const render = jest.fn();
1507+
1508+
const managerApi = createManagerApi({});
1509+
managerApi().registerField({ name: 'field', validate: asyncValidate1, render, internalId: 1 });
1510+
managerApi().registerField({ name: 'field', validate: asyncValidate2, render, internalId: 2 });
1511+
1512+
expect(managerApi().getFieldState('field').validating).toEqual(true);
1513+
expect(managerApi().getState().validating).toEqual(true);
1514+
1515+
jest.runAllTimers();
1516+
1517+
setImmediate(() => {
1518+
expect(managerApi().getFieldState('field').validating).toEqual(false);
1519+
expect(managerApi().getState().validating).toEqual(false);
1520+
1521+
managerApi().change('field', 'ok');
1522+
1523+
expect(managerApi().getFieldState('field').validating).toEqual(true);
1524+
expect(managerApi().getState().validating).toEqual(true);
1525+
1526+
jest.runAllTimers();
1527+
1528+
setImmediate(() => {
1529+
expect(managerApi().getFieldState('field').validating).toEqual(false);
1530+
expect(managerApi().getState().validating).toEqual(false);
1531+
done();
1532+
});
1533+
});
1534+
});
15021535
});
15031536

15041537
describe('initialize', () => {

packages/form-state-manager/src/types/manager-api.d.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ export interface AsyncWatcherApi {
5454
registerValidator: (callback: Promise<unknown>) => void;
5555
}
5656

57-
export type AsyncWatcher = (updateValidating: (validating: boolean) => void, updateSubmitting: (submitting: boolean) => void) => AsyncWatcherApi;
57+
export type AsyncWatcher = (
58+
updateValidating: (validating: boolean) => void,
59+
updateSubmitting: (submitting: boolean) => void,
60+
updateFormValidating: (increment: number) => void
61+
) => AsyncWatcherApi;
5862

5963
export type Rerender = (subscribeTo?: Array<string>) => void;
6064

packages/form-state-manager/src/utils/manager-api.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,19 @@ type objectMapFunction = (value: any, key: any) => any;
4646
// TODO: try to optimize
4747
const traverseObject = (object: AnyObject, callback: objectMapFunction) => Object.keys(object).forEach((key) => callback(object[key], key));
4848

49-
const asyncWatcher: AsyncWatcher = (updateValidating, updateSubmitting) => {
49+
const asyncWatcher: AsyncWatcher = (updateValidating, updateSubmitting, updateFormValidating) => {
5050
let nextKey = 0;
5151
const asyncValidators: AsyncWatcherRecord = {};
5252
// const asyncSubmissions: AsyncWatcherRecord = {};
5353

5454
const resolveValidator = (resolveKey: number): void => {
5555
delete asyncValidators[resolveKey];
56+
updateFormValidating(-1);
5657
updateValidating(Object.keys(asyncValidators).length !== 0);
5758
};
5859

5960
const registerValidator = (callback: Promise<unknown>) => {
61+
updateFormValidating(1);
6062
const resolveKey = nextKey;
6163
asyncValidators[nextKey] = callback;
6264
updateValidating(Object.keys(asyncValidators).length !== 0);
@@ -244,8 +246,20 @@ const createManagerApi: CreateManagerApi = ({
244246
let registeringField: string | number | undefined;
245247
let isSilent = false;
246248
let silentRender: string[] = [];
249+
let runningValidators = 0;
247250

248-
const asyncWatcherApi = asyncWatcher(updateValidating, updateSubmitting);
251+
function updateRunningValidators(increment: number): void {
252+
runningValidators = Math.max(runningValidators + increment, 0);
253+
254+
const validating = runningValidators > 0;
255+
256+
if (state.validating !== validating) {
257+
state.validating = validating;
258+
rerender(['validating']);
259+
}
260+
}
261+
262+
const asyncWatcherApi = asyncWatcher(updateValidating, updateSubmitting, updateRunningValidators);
249263

250264
const managerApi: ManagerApi = () => state;
251265

@@ -685,7 +699,7 @@ const createManagerApi: CreateManagerApi = ({
685699
state.fieldListeners[field.name].state.meta.validating = validating;
686700
};
687701

688-
const fieldAsyncWatcher = asyncWatcher(updateFieldValidating, () => undefined);
702+
const fieldAsyncWatcher = asyncWatcher(updateFieldValidating, () => undefined, updateRunningValidators);
689703
state.fieldListeners[field.name].asyncWatcher = fieldAsyncWatcher;
690704
}
691705

0 commit comments

Comments
 (0)