Skip to content

Commit f1bff65

Browse files
authored
Merge pull request #391 from rvsia/nestedConditions
feat(renderer): add proper not, and, or conditions
2 parents e1a262c + 319f73a commit f1bff65

File tree

7 files changed

+637
-50
lines changed

7 files changed

+637
-50
lines changed

packages/react-form-renderer/src/form-renderer/condition.js

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,60 @@ import get from 'lodash/get';
66

77
const isEmptyValue = (value) => typeof value === 'number' || value === true ? false : lodashIsEmpty(value);
88

9-
const Condition = ({ condition, children }) => {
10-
const fieldCondition = (value, { is, isNotEmpty, isEmpty, pattern, notMatch, flags }) => {
11-
if (isNotEmpty){
12-
return !isEmptyValue(value);
13-
}
9+
const fieldCondition = (value, { is, isNotEmpty, isEmpty, pattern, notMatch, flags }) => {
10+
if (isNotEmpty){
11+
return !isEmptyValue(value);
12+
}
1413

15-
if (isEmpty){
16-
return isEmptyValue(value);
17-
}
14+
if (isEmpty){
15+
return isEmptyValue(value);
16+
}
1817

19-
if (pattern) {
20-
const regExpPattern = RegExp(pattern, flags);
18+
if (pattern) {
19+
const regExpPattern = RegExp(pattern, flags);
2120

22-
return notMatch ? !regExpPattern.test(value) : regExpPattern.test(value);
23-
}
21+
return notMatch ? !regExpPattern.test(value) : regExpPattern.test(value);
22+
}
2423

25-
const isMatched = Array.isArray(is) ? !!is.includes(value) : value === is;
24+
const isMatched = Array.isArray(is) ? !!is.includes(value) : value === is;
2625

27-
return notMatch ? !isMatched : isMatched;
28-
};
26+
return notMatch ? !isMatched : isMatched;
27+
};
28+
29+
export const parseCondition = (condition, values) => {
30+
if (Array.isArray(condition)) {
31+
return !condition.map((condition) => parseCondition(condition, values)).some(result => result === false);
32+
}
2933

30-
const shouldRender = (values, conditionItem) => {
31-
if (typeof conditionItem.when === 'string') {
32-
return fieldCondition(get(values, conditionItem.when), conditionItem);
33-
}
34+
if (condition.and) {
35+
return condition.and.map((condition) => parseCondition(condition, values)).every(result => result === true);
36+
}
3437

35-
if (Array.isArray(conditionItem.when)) {
36-
return conditionItem.when.map(fieldName => fieldCondition(get(values, fieldName), conditionItem)).find(condition => !!condition);
37-
}
38+
if (condition.or) {
39+
return condition.or.map((condition) => parseCondition(condition, values)).some(result => result === true);
40+
}
3841

39-
return false;
40-
};
42+
if (condition.not) {
43+
return !parseCondition(condition.not, values);
44+
}
4145

42-
return (
43-
<FormSpy>
44-
{ ({ values }) => {
45-
const visible = Array.isArray(condition)
46-
? !condition.map(conditionItem => !!shouldRender(values, conditionItem)).some(result => result === false)
47-
: shouldRender(values, condition);
46+
if (typeof condition.when === 'string') {
47+
return fieldCondition(get(values, condition.when), condition);
48+
}
4849

49-
return visible ? children : null;
50-
} }
51-
</FormSpy>
52-
);
50+
if (Array.isArray(condition.when)) {
51+
return !!condition.when.map(fieldName => fieldCondition(get(values, fieldName), condition)).find(condition => !!condition);
52+
}
5353

54+
return false;
5455
};
5556

57+
const Condition = ({ condition, children }) => (
58+
<FormSpy>
59+
{ ({ values }) => parseCondition(condition, values) ? children : null }
60+
</FormSpy>
61+
);
62+
5663
const conditionProps = {
5764
when: PropTypes.string.isRequired,
5865
is: PropTypes.oneOfType([

packages/react-form-renderer/src/parsers/default-schema-validator.js

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,47 +22,63 @@ const checkCondition = (condition, fieldName) => {
2222
return condition.forEach(item => checkCondition(item, fieldName));
2323
}
2424

25+
if (condition.hasOwnProperty('and') && !Array.isArray(condition.and)) {
26+
throw new DefaultSchemaError(`
27+
Error occured in field definition with "name" property: "${fieldName}".
28+
'and' property in a field condition must be an array! Received: ${typeof condition.and}.
29+
`);
30+
}
31+
32+
if (condition.hasOwnProperty('or') && !Array.isArray(condition.and)) {
33+
throw new DefaultSchemaError(`
34+
Error occured in field definition with "name" property: "${fieldName}".
35+
'or' propery in a field condition must be an array! Received: ${typeof condition.and}.
36+
`);
37+
}
38+
2539
if (typeof condition !== 'object') {
2640
throw new DefaultSchemaError(`
2741
Error occured in field definition with name: "${fieldName}".
2842
Field condition must be an object, received ${Array.isArray(condition) ? 'array' : typeof condition}!
2943
`);
3044
}
3145

32-
if (!condition.hasOwnProperty('when')) {
33-
throw new DefaultSchemaError(`
46+
if (!condition.hasOwnProperty('and') && !condition.hasOwnProperty('or') && !condition.hasOwnProperty('not')) {
47+
if (!condition.hasOwnProperty('when')) {
48+
throw new DefaultSchemaError(`
3449
Error occured in field definition with "name" property: "${fieldName}".
3550
Field condition must have "when" property! Properties received: [${Object.keys(condition)}].
3651
`);
37-
}
52+
}
3853

39-
if (!(typeof condition.when === 'string' || Array.isArray(condition.when))) {
40-
throw new DefaultSchemaError(`
54+
if (!(typeof condition.when === 'string' || Array.isArray(condition.when))) {
55+
throw new DefaultSchemaError(`
4156
Error occured in field definition with name: "${fieldName}".
4257
Field condition property "when" must be oof type "string", ${typeof condition.when} received!].
4358
`);
44-
}
59+
}
4560

46-
if (!condition.hasOwnProperty('is') && !condition.hasOwnProperty('isEmpty')
61+
if (!condition.hasOwnProperty('is') && !condition.hasOwnProperty('isEmpty')
4762
&& !condition.hasOwnProperty('isNotEmpty') && !condition.hasOwnProperty('pattern')) {
48-
throw new DefaultSchemaError(`
63+
throw new DefaultSchemaError(`
4964
Error occured in field definition with name: "${fieldName}".
5065
Field condition must have one of "is", "isEmpty", "isNotEmpty", "pattern" property! Properties received: [${Object.keys(condition)}].
5166
`);
52-
}
67+
}
5368

54-
if (condition.hasOwnProperty('notMatch') && !condition.hasOwnProperty('pattern') && !condition.hasOwnProperty('is')) {
55-
throw new DefaultSchemaError(`
69+
if (condition.hasOwnProperty('notMatch') && !condition.hasOwnProperty('pattern') && !condition.hasOwnProperty('is')) {
70+
throw new DefaultSchemaError(`
5671
Error occured in field definition with name: "${fieldName}".
5772
Field condition must have "pattern" or "is" property when "notMatch" is set! Properties received: [${Object.keys(condition)}].
5873
`);
59-
}
74+
}
6075

61-
if (condition.hasOwnProperty('pattern') && (!(condition.pattern instanceof RegExp) && typeof condition.pattern !== 'string')) {
62-
throw new DefaultSchemaError(`
76+
if (condition.hasOwnProperty('pattern') && (!(condition.pattern instanceof RegExp) && typeof condition.pattern !== 'string')) {
77+
throw new DefaultSchemaError(`
6378
Error occured in field definition with name: "${fieldName}".
6479
Field condition must have "pattern" of instance "RegExp" or "string"! Instance received: [${condition.pattern.constructor.name}].
6580
`);
81+
}
6682
}
6783
};
6884

0 commit comments

Comments
 (0)