Skip to content

Commit 25fffb1

Browse files
committed
fix(renderer): nested condition based on form initial values
1 parent ba449d9 commit 25fffb1

File tree

5 files changed

+397
-55
lines changed

5 files changed

+397
-55
lines changed

packages/react-form-renderer/demo/form-fields-mapper.js

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* eslint-disable no-unused-vars */
22
import React from 'react';
3-
import { componentTypes } from '../src';
3+
import { componentTypes, useFormApi } from '../src';
44
import FieldProvider from '../src/field-provider';
55
import useFieldApi from '../src/use-field-api';
66

@@ -71,22 +71,71 @@ const AsyncComponent = (props) => {
7171
);
7272
};
7373

74+
const SubForm = ({ fields, title, ...props }) => {
75+
const formOptions = useFormApi();
76+
return (
77+
<div>
78+
<h2>{title}</h2>
79+
<div>{formOptions.renderForm(fields)}</div>
80+
</div>
81+
);
82+
};
83+
84+
const RadioOption = ({ name, option }) => {
85+
const { input } = useFieldApi({
86+
name,
87+
type: 'radio',
88+
value: option.value,
89+
});
90+
return (
91+
<div>
92+
<label htmlFor={option.label}>{option.label}</label>
93+
<input
94+
type="radio"
95+
{...input}
96+
id={option.label}
97+
name={name}
98+
onChange={(e) => {
99+
input.onChange(option.value);
100+
}}
101+
/>
102+
</div>
103+
);
104+
};
105+
106+
const Radio = (props) => {
107+
const { label, options } = useFieldApi({
108+
...props,
109+
type: 'radio',
110+
});
111+
return (
112+
<div>
113+
<fieldset>
114+
<legend>{label}</legend>
115+
{options.map(({ value, label }) => {
116+
return <RadioOption key={value} option={{ value, label }} name={props.name} />;
117+
})}
118+
</fieldset>
119+
</div>
120+
);
121+
};
122+
74123
const mapper = {
75124
[componentTypes.TEXT_FIELD]: TextField,
76125
[componentTypes.TEXTAREA]: TextField,
77126
[componentTypes.SELECT]: SelectField,
78127
[componentTypes.CHECKBOX]: (props) => <div>checkbox</div>,
79-
[componentTypes.SUB_FORM]: (props) => <div>sub form</div>,
80-
[componentTypes.RADIO]: (props) => <div>radio</div>,
128+
[componentTypes.SUB_FORM]: SubForm,
129+
[componentTypes.RADIO]: Radio,
81130
[componentTypes.TABS]: (props) => <div>tabs</div>,
82131
[componentTypes.TAB_ITEM]: (props) => <div>tab item</div>,
83132
[componentTypes.DATE_PICKER]: (props) => <div>date picker</div>,
84133
[componentTypes.TIME_PICKER]: (props) => <div>time picker</div>,
85134
dataShower: AsyncComponent,
86135
'composite-mapper-field': {
87136
component: TextField,
88-
className: 'composite-component-class'
89-
}
137+
className: 'composite-component-class',
138+
},
90139
};
91140

92141
export default mapper;

packages/react-form-renderer/demo/index.js

Lines changed: 92 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,112 @@ import FormTemplate from './form-template';
77
import mapper from './form-fields-mapper';
88

99
const schema = {
10-
title: 'Set action',
1110
fields: [
1211
{
13-
component: 'text-field',
14-
name: 'useDefaultNickName',
15-
label: 'Do you want to use default nickname?',
16-
description: 'set: {} is used to reset the setter',
12+
name: 'formRadio',
13+
label: 'SelectSubForm',
14+
component: 'radio',
15+
initializeOnMount: true,
16+
clearOnUnmount: true,
17+
options: [
18+
{ label: 'form1', value: 'form1' },
19+
{ label: 'form2', value: 'form2' },
20+
],
1721
},
1822
{
19-
component: 'text-field',
20-
name: 'nickname',
21-
label: 'Nickname',
23+
component: 'sub-form',
24+
name: 'subform1',
2225
condition: {
23-
when: 'useDefaultNickName',
24-
is: 'a',
25-
then: {
26-
set: (formState, getFieldState) => {
27-
return { nickname: formState.values.useDefaultNickName };
26+
when: 'formRadio',
27+
is: 'form1',
28+
},
29+
fields: [
30+
{
31+
name: 'txt1',
32+
label: 'Enter text',
33+
initializeOnMount: true,
34+
clearOnUnmount: true,
35+
component: 'text-field',
36+
},
37+
{
38+
name: 'radioBtn',
39+
label: 'Select',
40+
component: 'radio',
41+
initializeOnMount: true,
42+
clearOnUnmount: true,
43+
options: [
44+
{ label: 'abc', value: 'abc' },
45+
{ label: 'def', value: 'def' },
46+
],
47+
},
48+
{
49+
name: 'txtField2',
50+
label: 'Radio1',
51+
initializeOnMount: true,
52+
clearOnUnmount: true,
53+
component: 'text-field',
54+
condition: {
55+
when: 'radioBtn',
56+
is: 'def',
2857
},
2958
},
30-
else: { visible: true, set: {} },
59+
],
60+
},
61+
{
62+
component: 'sub-form',
63+
title: 'Subform2',
64+
description: 'This is a subform',
65+
name: 'subform2',
66+
condition: {
67+
when: 'formRadio',
68+
is: 'form2',
3169
},
70+
fields: [
71+
{
72+
name: 'radioBtn2',
73+
label: 'Select',
74+
component: 'radio',
75+
initializeOnMount: true,
76+
clearOnUnmount: true,
77+
options: [
78+
{ label: 'pqr', value: 'pqr' },
79+
{ label: 'stu', value: 'stu' },
80+
],
81+
},
82+
{
83+
name: 'txtField3',
84+
label: 'Radio1',
85+
initializeOnMount: true,
86+
clearOnUnmount: true,
87+
component: 'text-field',
88+
condition: {
89+
and: [
90+
{
91+
when: 'radioBtn2',
92+
is: 'stu',
93+
},
94+
{
95+
when: 'formRadio',
96+
is: 'form2',
97+
},
98+
],
99+
},
100+
},
101+
],
32102
},
33103
],
34104
};
105+
106+
const initialValues = {
107+
formRadio: 'form2',
108+
radioBtn2: 'stu',
109+
txtField3: 'data',
110+
};
111+
35112
const App = () => {
36113
return (
37114
<div style={{ padding: 20 }}>
38-
<FormRenderer componentMapper={mapper} onSubmit={console.log} FormTemplate={FormTemplate} schema={schema} />
115+
<FormRenderer initialValues={initialValues} componentMapper={mapper} onSubmit={console.log} FormTemplate={FormTemplate} schema={schema} />
39116
</div>
40117
);
41118
};

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ const Condition = React.memo(
4343
initial: true,
4444
});
4545

46-
const conditionResult = parseCondition(condition, values, field);
46+
// It is required to get the context state values from in order to get the latest state.
47+
// Using the trigger values can cause issues with the radio field as each input is registered separately to state and does not yield the actual field value.
48+
const conditionResult = parseCondition(condition, formOptions.getState().values, field);
49+
4750
const setters = conditionResult.set ? [conditionResult.set] : conditionResult.sets;
4851

4952
useEffect(() => {
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
{
2+
"schema": {
3+
"fields": [
4+
{
5+
"name": "formRadio",
6+
"label": "SelectSubForm",
7+
"component": "radio",
8+
"initializeOnMount": true,
9+
"clearOnUnmount": true,
10+
"options": [
11+
{ "label": "form1", "value": "form1" },
12+
{ "label": "form2", "value": "form2" }
13+
]
14+
},
15+
{
16+
"component": "sub-form",
17+
"name": "subform1",
18+
"condition": {
19+
"when": "formRadio",
20+
"is": "form1"
21+
},
22+
"fields": [
23+
{
24+
"name": "txt1",
25+
"label": "Enter text",
26+
"initializeOnMount": true,
27+
"clearOnUnmount": true,
28+
"component": "text-field"
29+
},
30+
{
31+
"name": "radioBtn",
32+
"label": "Select",
33+
"component": "radio",
34+
"initializeOnMount": true,
35+
"clearOnUnmount": true,
36+
"options": [
37+
{ "label": "abc", "value": "abc" },
38+
{ "label": "def", "value": "def" }
39+
]
40+
},
41+
{
42+
"name": "txtField2",
43+
"label": "Radio1",
44+
"initializeOnMount": true,
45+
"clearOnUnmount": true,
46+
"component": "text-field",
47+
"condition": {
48+
"when": "radioBtn",
49+
"is": "def"
50+
}
51+
}
52+
]
53+
},
54+
{
55+
"component": "sub-form",
56+
"name": "subform2",
57+
"condition": {
58+
"when": "formRadio",
59+
"is": "form2"
60+
},
61+
"fields": [
62+
{
63+
"name": "radioBtn2",
64+
"label": "Select",
65+
"component": "radio",
66+
"initializeOnMount": true,
67+
"clearOnUnmount": true,
68+
"options": [
69+
{ "label": "pqr", "value": "pqr" },
70+
{ "label": "stu", "value": "stu" }
71+
]
72+
},
73+
{
74+
"name": "txtField3",
75+
"label": "Radio1",
76+
"initializeOnMount": true,
77+
"clearOnUnmount": true,
78+
"component": "text-field",
79+
"condition": {
80+
"and": [
81+
{
82+
"when": "radioBtn2",
83+
"is": "stu"
84+
},
85+
{
86+
"when": "formRadio",
87+
"is": "form2"
88+
}
89+
]
90+
}
91+
}
92+
]
93+
}
94+
]
95+
},
96+
"initialValues": {
97+
"formRadio": "form2",
98+
"radioBtn2": "stu",
99+
"txtField3": "data"
100+
}
101+
}

0 commit comments

Comments
 (0)