diff --git a/packages/react-form-renderer/demo/index.js b/packages/react-form-renderer/demo/index.js
index b5844eac0..d909709ed 100644
--- a/packages/react-form-renderer/demo/index.js
+++ b/packages/react-form-renderer/demo/index.js
@@ -9,17 +9,78 @@ const fileSchema = {
fields: [
{
component: 'text-field',
- name: 'file-upload',
- type: 'file',
- label: 'file upload'
- }
- ]
+ name: 'field1',
+ label: 'Field1 (try "abc")',
+ },
+ {
+ component: 'text-field',
+ name: 'field2',
+ label: 'Field2 (try "xyz")',
+ hideField: true,
+ },
+ {
+ component: 'text-field',
+ name: 'field3',
+ label: 'Field3 (try "123")',
+ },
+ {
+ component: 'text-field',
+ name: 'field4',
+ label: 'Field4',
+ },
+
+ {
+ component: 'text-field',
+ name: 'field5',
+ label: 'Field5',
+ condition: {
+ when: 'field1',
+ is: 'cba',
+ },
+ },
+ ],
+ conditions: {
+ cond1: {
+ when: 'fieldx',
+ is: 'abc',
+ then: {
+ field4: {
+ disabled: true,
+ set: 'New value for field4',
+ },
+ field3: {
+ disabled: true,
+ },
+ field2: {
+ visible: true,
+ },
+ },
+ },
+ cond2: {
+ when: 'field3',
+ is: '123',
+ then: {
+ field3: {
+ visible: false,
+ },
+ },
+ },
+ cond3: {
+ when: 'field2',
+ is: 'xyz',
+ then: {
+ field3: {
+ visible: false,
+ },
+ },
+ },
+ },
};
const App = () => {
// const [values, setValues] = useState({});
return (
-
+
console.log(values, args)}
diff --git a/packages/react-form-renderer/src/files/conditions-mapper.js b/packages/react-form-renderer/src/files/conditions-mapper.js
new file mode 100644
index 000000000..a4448dd0d
--- /dev/null
+++ b/packages/react-form-renderer/src/files/conditions-mapper.js
@@ -0,0 +1,85 @@
+/*
+ conditionsMapper will remap a conditions object and create an object with each depending fieldName as a key.
+
+ Since one field can be involed in more than one condition, an array of condition references will be created under each fieldName key
+
+ Since more than one field can be involved in the same condition, the same condition might be referenced from
+ several condition arrays.
+*/
+
+function isObject(obj) {
+ return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
+}
+
+function isArray(obj) {
+ return Array.isArray(obj);
+}
+
+export const conditionsMapper = ({conditions}) => {
+ if (!conditions) return {};
+
+ function traverse({obj, fnc, key}) {
+ fnc && fnc({obj, key});
+
+ if (isArray(obj)) {
+ traverseArray({
+ obj,
+ fnc,
+ key,
+ });
+ } else if (isObject(obj)) {
+ traverseObject({
+ obj,
+ fnc,
+ key,
+ });
+ }
+ }
+
+ function traverseArray({obj, fnc, key}) {
+ obj.forEach(([key, item]) => {
+ traverse({
+ obj: item,
+ fnc,
+ key,
+ });
+ });
+ }
+
+ function traverseObject({obj, fnc, key}) {
+ Object.entries(obj).forEach(([key, item]) => {
+ traverse({
+ obj: item,
+ fnc,
+ key,
+ });
+ });
+ }
+
+ const indexedConditions = {};
+ const conditionArray = Object.entries(conditions);
+
+ conditionArray
+ .map(([key, condition]) => {
+ return {
+ key: key,
+ ...condition,
+ };
+ })
+ .forEach(condition => {
+ traverse({
+ obj: condition,
+ fnc: ({obj, key}) => {
+ if (key === 'when') {
+ const fieldNames = isArray(obj) ? obj : [obj];
+ fieldNames.map(fieldName => {
+ indexedConditions[fieldName] = indexedConditions[fieldName] || [];
+ indexedConditions[fieldName].push(condition);
+ });
+ }
+ },
+ });
+ });
+
+ return indexedConditions;
+};
diff --git a/packages/react-form-renderer/src/files/form-renderer.js b/packages/react-form-renderer/src/files/form-renderer.js
index 878cb62c0..d100f3742 100644
--- a/packages/react-form-renderer/src/files/form-renderer.js
+++ b/packages/react-form-renderer/src/files/form-renderer.js
@@ -1,4 +1,4 @@
-import React, { useState, useRef } from 'react';
+import React, {useState, useRef, useReducer} from 'react';
import Form from './form';
import arrayMutators from 'final-form-arrays';
import PropTypes from 'prop-types';
@@ -9,6 +9,9 @@ import renderForm from '../form-renderer/render-form';
import defaultSchemaValidator from './default-schema-validator';
import SchemaErrorComponent from '../form-renderer/schema-error-component';
import defaultValidatorMapper from './validator-mapper';
+import RegisterConditions from './register-conditions';
+import SetFieldValues from './set-field-values';
+import uiStateReducer from './ui-state-reducer';
const FormRenderer = ({
componentMapper,
@@ -26,15 +29,25 @@ const FormRenderer = ({
...props
}) => {
const [fileInputs, setFileInputs] = useState([]);
+ const [uiState, dispatchUIState] = useReducer(uiStateReducer, {
+ fields: {},
+ setFieldValues: {},
+ });
const focusDecorator = useRef(createFocusDecorator());
let schemaError;
- const validatorMapperMerged = { ...defaultValidatorMapper, ...validatorMapper };
+ const validatorMapperMerged = {...defaultValidatorMapper, ...validatorMapper};
try {
const validatorTypes = Object.keys(validatorMapperMerged);
const actionTypes = actionMapper ? Object.keys(actionMapper) : [];
- defaultSchemaValidator(schema, componentMapper, validatorTypes, actionTypes, schemaValidatorMapper);
+ defaultSchemaValidator(
+ schema,
+ componentMapper,
+ validatorTypes,
+ actionTypes,
+ schemaValidatorMapper
+ );
} catch (error) {
schemaError = error;
console.error(error);
@@ -45,18 +58,24 @@ const FormRenderer = ({
return ;
}
- const registerInputFile = (name) => setFileInputs((prevFiles) => [...prevFiles, name]);
+ const registerInputFile = name => setFileInputs(prevFiles => [...prevFiles, name]);
- const unRegisterInputFile = (name) => setFileInputs((prevFiles) => [...prevFiles.splice(prevFiles.indexOf(name))]);
+ const unRegisterInputFile = name =>
+ setFileInputs(prevFiles => [...prevFiles.splice(prevFiles.indexOf(name))]);
return (