Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New conditions handler (defined globally for schema instead of locally for field) #652

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

msageryd
Copy link

My proposal for a new conditions handler:

  • conditions are defined "globally" instead of "locally" per field
  • field listeners are registered only for fields involved in "when-clauses"
  • the relevant conditions are added as custom data for each field listener (field.data.conditions)
  • when conditions triggers, the resulting ui-effects are added to uiState for affected fields via uiStateReducer
  • when conditions de-driggers, the ui-effects are removed
  • uiState is available in useFormApi(). Any component can check the uiState to decide how/if it should render
  • set-instructions in conditions are "one-shot". I.e. when the new field value is set, the set instruction is removed.

TODO:

  • TypeScript (I don't know TS, so I'm not the right man to add typing)
  • Backwards compability for old conditions structure (should probably be handled at the top of RegisterConditions).
  • My conditionParser differs some from the old one. I put mine in conditions2.js in order to not break other stuff.
  • uiStateReducer originally user Immer in my code. I took some shortcuts with the immutability when I removed Immer. This should probably be addressed.
  • Documentation
  • Decide how to use uiState (hiding and disabling fields etc)
  • Circular conditions are possible. It's kind of hard to walk into this problem, but it should probably be handled some way.

I'm sure there are lots to discuss before this reaches production.

@Hyperkid123 Hyperkid123 self-assigned this Jul 16, 2020
@Hyperkid123 Hyperkid123 added enhancement New feature or request renderer React form renderer PR labels Jul 16, 2020
feat: better example conditions in the schema
feat: debug-div changed to pre for better JSON-rendering
chore: dispatchCondition renamed to dispatchUIState for clarity
chore: dispatch after parseCondition is now separated into two different dispatches (add/remove) for clarity
@Hyperkid123
Copy link
Member

So the rendering performance seems solid. Looking at the profiler, the only time when multiple fields are re-rendered in the same cycle is when a condition is met/broken which makes sense and has to happen. 👍 on that.

I will now dig a bit deeper trough the code.

Copy link
Member

@Hyperkid123 Hyperkid123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks very good and would a great addition. Other than just a convention difference from current code (which can be addressed later) I have just a small number of comments.

But the approach is good and I like it. Once you are done with your checklist we will make a thorough review. 👍

chore: switched from for-loop to entries-iteration
chore: moved utility functions isObject and isArray to outside of the conditionsMapper
@msageryd
Copy link
Author

DONE:

  • uiStateReducer originally user Immer in my code. I took some shortcuts with the immutability when I removed Immer. This should probably be addressed.
    Fixed in commit 12ce210

  • Circular conditions are possible. It's kind of hard to walk into this problem, but it should probably be handled some way.
    I cannot reproduce my circular scenario anymore. I'm guessing that this problem is solved due to the better immutability handling in uiStateReducer.

N.B. legacy condition definitions will not work in this version. A soon to come legacyConditionsMapper will solve this.
chore: replaced condition.js with condition2.js (new handler)
chore: removed Conditions and FormConditionsWrapper components from render-form.js
chore: implemented new conditions-handler in render-form.js, including support for "visible" and "disabled"
@msageryd
Copy link
Author

msageryd commented Jul 17, 2020

DONE (98d2064):

  • My conditionParser differs some from the old one. I put mine in conditions2.js in order to not break other stuff.
    conditions2.js has now replaced the old conditions.js. This will break legacy condition definitions. A future legacyConditionsMapper will convert old definitions to the new structure and un-break this

  • Decide how to use uiState (hiding and disabling fields etc)
    I decided that FormFieldConditionWrapper should be removed. The condition data is already available in uiState in context and used as input to FormFieldHideWrapper

@msageryd
Copy link
Author

@Hyperkid123 Some design questions:

Do you want the conditions collection to be an object or an array?

Object pros:

  • Forces user to define names for each condition.
  • Easier to debug with good names.
  • Easier to merge multiple conditions objects

Array pros:

  • Persisted order of conditions

Is support for sequence still needed?

You said earlier that you wanted to get rid of sequence conditions. Does this mean that the legacyConditionsMapper does not have to cover sequences?

* master:
  Release of new version: 2.8.0 <no> [skip ci]
  Add resolveProps type
  PF3 datepicker test timezone fix
  Add documentation page for resolve props
  Add tests for resolve props
  feat(renderer): add resolveProps option

# Conflicts:
#	packages/react-form-renderer/src/form-renderer/render-form.js
- manually merged
@msageryd
Copy link
Author

@Hyperkid123 I can't find any repo for the documentation. Thought I'd update the docs for the new conditions schema.

…s otherwise

fix: field.hideField was not taken into consideration in FormFieldWrapper
@msageryd msageryd changed the title First commit on new conditions handler New conditions handler (defined globally for schema instead of locally for field) Jul 18, 2020
@msageryd
Copy link
Author

@Hyperkid123 I've implemented a naive legacyConditionsMapper. It can only handle simple visibility conditions for now. This needs to be revisited in order to handle more complex conditions. f1818eb

@msageryd
Copy link
Author

@Hyperkid123 I have started to update the tests for conditions. How do I run the tests? yarn test seems to run the tests, but all test fails, so I suppose I need to do something more.

@Hyperkid123
Copy link
Member

@msageryd sorry for the silence (weekend). Going through the changes now.

@Hyperkid123
Copy link
Member

I decided that FormFieldConditionWrapper should be removed. The condition data is already available in uiState in context and used as input to FormFieldHideWrapper

This might cause issues with the value initialization and submission. There is a difference between the condition wrapper and the hidden wrapper.

If the condition is not met the field is not in the DOM and once the condition is met you can trigger mounting events like re-initialize the field. So if the condition is false the value is not sent to the submit callback. Yes value of the condition can be persisted even if it's hidden but that is aa opt-in attribute.

If the hideField is true, the filed is not visible but still present in the DOM and its value is submitted. It is basically an input of type hidden for non-input fields.

So the condition wrapper might no longer be required but we still need to detach/attach the field from/to the DOM.

@Hyperkid123
Copy link
Member

Do you want the conditions collection to be an object or an array?

From the development point of view, the object is preferable. But the order of execution is important and it makes it a bit easier for a user to understand and define the condition order. That is ultimately the reason why the whole schema is a nested array since its sometimes created by users who do not necessarily have any experience with any development. I would like to stick with the Array if possible.

Is support for sequence still needed?

You said earlier that you wanted to get rid of sequence conditions. Does this mean that the legacyConditionsMapper does not have to cover sequences?

Sequences still have to be supported. We have to keep them at least until the next major release. We introduced them to ensure the correct order of execution of conditions using AND and OR statements when we introduced the set outcome of a condition.

@Hyperkid123
Copy link
Member

@Hyperkid123 I can't find any repo for the documentation. Thought I'd update the docs for the new conditions schema.

its the react-renderer-demo package (I know what an intuitive name for a docs package). https://data-driven-forms.org/development-setup#rundocumentation

I would like to add that if run locally, the docs use locally build packages so it is required that all packages are built on your local machine. Running yarn build in the root directly would do that for you.

@Hyperkid123
Copy link
Member

@Hyperkid123 I have started to update the tests for conditions. How do I run the tests? yarn test seems to run the tests, but all test fails, so I suppose I need to do something more.

There is the same requirement as with the docs. All packages must be built locally in since the tests use a local build of all packages. This is there to ensure that no matter what changes in what packages you make, it will run all the tests with all of these changes. If you have all packages build already and you still see some error, just post the stack trace here and we can look at it.

But looking at the circle CI log, you have a circular dependency so the renderer package wont even build:

./src/index.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/component-types.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/compose-validators.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/conditions-mapper.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/data-types.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/default-schema-validator.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/field-array.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/field-provider.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/form-renderer.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/form-spy.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/form.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/legacy-conditions.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/register-conditions.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/renderer-context.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/schema-errors.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/set-field-values.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/ui-state-reducer.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/use-field-api.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/use-form-api.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/validator-mapper.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/validator-types.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/validators.js, /home/circleci/react-forms/packages/react-form-renderer/src/files/wizard-context.js → ./dist/cjs...
 
[!] Error: Circular dependency: src/index.js -> src/files/form-renderer.js -> src/files/register-conditions.js -> src/index.js
 
Error: Circular dependency: src/index.js -> src/files/form-renderer.js -> src/files/register-conditions.js -> src/index.js
 
    at Object.onwarn (/home/circleci/react-forms/packages/react-form-renderer/rollup.config.js:43:9)
 
    at Object.config.onwarn.warning [as onwarn] (/home/circleci/react-forms/node_modules/rollup/dist/shared/node-entry.js:13599:25)
 
    at Graph.config.onwarn.warning [as onwarn] (/home/circleci/react-forms/node_modules/rollup/dist/shared/node-entry.js:13599:25)
 
    at Graph.warn (/home/circleci/react-forms/node_modules/rollup/dist/shared/node-entry.js:13403:14)
 
    at Graph.link (/home/circleci/react-forms/node_modules/rollup/dist/shared/node-entry.js:13420:18)
 
    at Promise.all.then (/home/circleci/react-forms/node_modules/rollup/dist/shared/node-entry.js:13286:18)
 
    at process._tickCallback (internal/process/next_tick.js:68:7)
 

That may be the reason why the tests fail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request renderer React form renderer PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants