Skip to content

Commit 733eb87

Browse files
committed
feat(renderer): add proper not, and, or conditions
1 parent c0b9ca9 commit 733eb87

File tree

7 files changed

+708
-65
lines changed

7 files changed

+708
-65
lines changed

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

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -24,51 +24,67 @@ const checkCondition = (condition, fieldName) => {
2424
return condition.forEach((item) => checkCondition(item, fieldName));
2525
}
2626

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

34-
if (!condition.hasOwnProperty('when')) {
35-
throw new DefaultSchemaError(`
48+
if (!condition.hasOwnProperty('and') && !condition.hasOwnProperty('or') && !condition.hasOwnProperty('not')) {
49+
if (!condition.hasOwnProperty('when')) {
50+
throw new DefaultSchemaError(`
3651
Error occured in field definition with "name" property: "${fieldName}".
3752
Field condition must have "when" property! Properties received: [${Object.keys(condition)}].
3853
`);
39-
}
54+
}
4055

41-
if (!(typeof condition.when === 'string' || Array.isArray(condition.when))) {
42-
throw new DefaultSchemaError(`
56+
if (!(typeof condition.when === 'string' || Array.isArray(condition.when))) {
57+
throw new DefaultSchemaError(`
4358
Error occured in field definition with name: "${fieldName}".
4459
Field condition property "when" must be oof type "string", ${typeof condition.when} received!].
4560
`);
46-
}
61+
}
4762

48-
if (
49-
!condition.hasOwnProperty('is') &&
50-
!condition.hasOwnProperty('isEmpty') &&
51-
!condition.hasOwnProperty('isNotEmpty') &&
52-
!condition.hasOwnProperty('pattern')
53-
) {
54-
throw new DefaultSchemaError(`
63+
if (
64+
!condition.hasOwnProperty('is') &&
65+
!condition.hasOwnProperty('isEmpty') &&
66+
!condition.hasOwnProperty('isNotEmpty') &&
67+
!condition.hasOwnProperty('pattern')
68+
) {
69+
throw new DefaultSchemaError(`
5570
Error occured in field definition with name: "${fieldName}".
5671
Field condition must have one of "is", "isEmpty", "isNotEmpty", "pattern" property! Properties received: [${Object.keys(condition)}].
5772
`);
58-
}
73+
}
5974

60-
if (condition.hasOwnProperty('notMatch') && !condition.hasOwnProperty('pattern') && !condition.hasOwnProperty('is')) {
61-
throw new DefaultSchemaError(`
75+
if (condition.hasOwnProperty('notMatch') && !condition.hasOwnProperty('pattern') && !condition.hasOwnProperty('is')) {
76+
throw new DefaultSchemaError(`
6277
Error occured in field definition with name: "${fieldName}".
6378
Field condition must have "pattern" or "is" property when "notMatch" is set! Properties received: [${Object.keys(condition)}].
6479
`);
65-
}
80+
}
6681

67-
if (condition.hasOwnProperty('pattern') && !(condition.pattern instanceof RegExp) && typeof condition.pattern !== 'string') {
68-
throw new DefaultSchemaError(`
82+
if (condition.hasOwnProperty('pattern') && !(condition.pattern instanceof RegExp) && typeof condition.pattern !== 'string') {
83+
throw new DefaultSchemaError(`
6984
Error occured in field definition with name: "${fieldName}".
7085
Field condition must have "pattern" of instance "RegExp" or "string"! Instance received: [${condition.pattern.constructor.name}].
7186
`);
87+
}
7288
}
7389
};
7490

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

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,56 @@ 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-
}
14-
15-
if (isEmpty) {
16-
return isEmptyValue(value);
17-
}
18-
19-
if (pattern) {
20-
const regExpPattern = RegExp(pattern, flags);
21-
22-
return notMatch ? !regExpPattern.test(value) : regExpPattern.test(value);
23-
}
24-
25-
const isMatched = Array.isArray(is) ? !!is.includes(value) : value === is;
26-
27-
return notMatch ? !isMatched : isMatched;
28-
};
29-
30-
const shouldRender = (values, conditionItem) => {
31-
if (typeof conditionItem.when === 'string') {
32-
return fieldCondition(get(values, conditionItem.when), conditionItem);
33-
}
34-
35-
if (Array.isArray(conditionItem.when)) {
36-
return conditionItem.when.map((fieldName) => fieldCondition(get(values, fieldName), conditionItem)).find((condition) => !!condition);
37-
}
38-
39-
return false;
40-
};
41-
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);
48-
49-
return visible ? children : null;
50-
}}
51-
</FormSpy>
52-
);
9+
const fieldCondition = (value, { is, isNotEmpty, isEmpty, pattern, notMatch, flags }) => {
10+
if (isNotEmpty) {
11+
return !isEmptyValue(value);
12+
}
13+
14+
if (isEmpty) {
15+
return isEmptyValue(value);
16+
}
17+
18+
if (pattern) {
19+
const regExpPattern = RegExp(pattern, flags);
20+
21+
return notMatch ? !regExpPattern.test(value) : regExpPattern.test(value);
22+
}
23+
24+
const isMatched = Array.isArray(is) ? !!is.includes(value) : value === is;
25+
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+
}
33+
34+
if (condition.and) {
35+
return condition.and.map((condition) => parseCondition(condition, values)).every((result) => result === true);
36+
}
37+
38+
if (condition.or) {
39+
return condition.or.map((condition) => parseCondition(condition, values)).some((result) => result === true);
40+
}
41+
42+
if (condition.not) {
43+
return !parseCondition(condition.not, values);
44+
}
45+
46+
if (typeof condition.when === 'string') {
47+
return fieldCondition(get(values, condition.when), condition);
48+
}
49+
50+
if (Array.isArray(condition.when)) {
51+
return !!condition.when.map((fieldName) => fieldCondition(get(values, fieldName), condition)).find((condition) => !!condition);
52+
}
53+
54+
return false;
5355
};
5456

57+
const Condition = ({ condition, children }) => <FormSpy>{({ values }) => (parseCondition(condition, values) ? children : null)}</FormSpy>;
58+
5559
const conditionProps = {
5660
when: PropTypes.string.isRequired,
5761
is: PropTypes.oneOfType([PropTypes.array, PropTypes.string, PropTypes.object, PropTypes.number, PropTypes.bool]).isRequired,

0 commit comments

Comments
 (0)