Skip to content
This repository was archived by the owner on Aug 23, 2022. It is now read-only.

Commit 5cf9d09

Browse files
committed
Do not run async validations if field is invalid by sync validity. Fixes #329
1 parent fbe3ee8 commit 5cf9d09

File tree

3 files changed

+78
-32
lines changed

3 files changed

+78
-32
lines changed

src/components/control-component.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,22 @@ class Control extends Component {
273273
model,
274274
} = this.props;
275275

276+
// If there are no async validators,
277+
// do not run async validation
276278
if (!asyncValidators) return false;
277279

280+
// If any sync validity is invalid,
281+
// do not run async validation
282+
const asyncValidatorKeys = Object.keys(asyncValidators);
283+
const syncValid = Object.keys(fieldValue.validity).every((key) => {
284+
// If validity is based on async validator, skip
285+
if (!!~asyncValidatorKeys.indexOf(key)) return true;
286+
287+
return fieldValue.validity[key];
288+
});
289+
290+
if (!syncValid) return false;
291+
278292
return (dispatch) => {
279293
mapValues(asyncValidators,
280294
(validator, key) => dispatch(actions.asyncSetValidity(model,

test/control-component-spec.js

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -722,23 +722,23 @@ describe('Extended Control components', () => {
722722
test: modelReducer('test', {}),
723723
});
724724

725-
it('async validation should not override sync validity', () => {
726-
const field = TestUtils.renderIntoDocument(
727-
<Provider store={store}>
728-
<Control.text
729-
model="test.foo"
730-
validators={{
731-
required: (val) => val && val.length,
732-
}}
733-
asyncValidators={{
734-
asyncValid: (_, asyncDone) => asyncDone(false),
735-
}}
736-
/>
737-
</Provider>
738-
);
725+
const field = TestUtils.renderIntoDocument(
726+
<Provider store={store}>
727+
<Control.text
728+
model="test.foo"
729+
validators={{
730+
required: (val) => val && val.length,
731+
}}
732+
asyncValidators={{
733+
asyncValid: (_, asyncDone) => asyncDone(false),
734+
}}
735+
/>
736+
</Provider>
737+
);
739738

740-
const input = TestUtils.findRenderedDOMComponentWithTag(field, 'input');
739+
const input = TestUtils.findRenderedDOMComponentWithTag(field, 'input');
741740

741+
it('async validation should not run when field is invalid', () => {
742742
input.value = '';
743743
TestUtils.Simulate.change(input);
744744
TestUtils.Simulate.blur(input);
@@ -747,6 +747,22 @@ describe('Extended Control components', () => {
747747
store.getState().testForm.foo.validity,
748748
{
749749
required: false,
750+
});
751+
752+
assert.isUndefined(store.getState().testForm.foo.validity.asyncValid);
753+
});
754+
755+
it('async validation should not override sync validity', () => {
756+
input.value = 'asdf';
757+
TestUtils.Simulate.change(input);
758+
TestUtils.Simulate.blur(input);
759+
760+
assert.isDefined(store.getState().testForm.foo.validity.asyncValid);
761+
762+
assert.deepEqual(
763+
store.getState().testForm.foo.validity,
764+
{
765+
required: true,
750766
asyncValid: false,
751767
});
752768
});

test/field-component-spec.js

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -941,25 +941,25 @@ Object.keys(testContexts).forEach((testKey) => {
941941
test: modelReducer('test', {}),
942942
}));
943943

944-
it('async validation should not override sync validity', () => {
945-
const field = TestUtils.renderIntoDocument(
946-
<Provider store={store}>
947-
<Field
948-
model="test.foo"
949-
validators={{
950-
required: (val) => val && val.length,
951-
}}
952-
asyncValidators={{
953-
asyncValid: (_, asyncDone) => asyncDone(false),
954-
}}
955-
>
956-
<input type="text" />
957-
</Field>
958-
</Provider>
959-
);
944+
const field = TestUtils.renderIntoDocument(
945+
<Provider store={store}>
946+
<Field
947+
model="test.foo"
948+
validators={{
949+
required: (val) => val && val.length,
950+
}}
951+
asyncValidators={{
952+
asyncValid: (_, asyncDone) => asyncDone(false),
953+
}}
954+
>
955+
<input type="text" />
956+
</Field>
957+
</Provider>
958+
);
960959

961-
const input = TestUtils.findRenderedDOMComponentWithTag(field, 'input');
960+
const input = TestUtils.findRenderedDOMComponentWithTag(field, 'input');
962961

962+
it('async validation should not run when field is invalid', () => {
963963
input.value = '';
964964
TestUtils.Simulate.change(input);
965965
TestUtils.Simulate.blur(input);
@@ -968,6 +968,22 @@ Object.keys(testContexts).forEach((testKey) => {
968968
store.getState().testForm.foo.validity,
969969
{
970970
required: false,
971+
});
972+
973+
assert.isUndefined(store.getState().testForm.foo.validity.asyncValid);
974+
});
975+
976+
it('async validation should not override sync validity', () => {
977+
input.value = 'asdf';
978+
TestUtils.Simulate.change(input);
979+
TestUtils.Simulate.blur(input);
980+
981+
assert.isDefined(store.getState().testForm.foo.validity.asyncValid);
982+
983+
assert.deepEqual(
984+
store.getState().testForm.foo.validity,
985+
{
986+
required: true,
971987
asyncValid: false,
972988
});
973989
});

0 commit comments

Comments
 (0)