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

Refactor the component paths to ensure we are always referencing the correct path. #193

Merged
merged 6 commits into from
Dec 9, 2024

Conversation

travist
Copy link
Member

@travist travist commented Nov 19, 2024

Before this change, the core library was trying to accomplish multiple "pathing" strategies using the single "path" variable passed through both the "eachComponent" as well as the "eachComponentData" methods. These paths were not following any strict rules on how they behaved causing MANY downstream issues with the renderer and data processing systems. This pull requests solves this issue by creating a very deterministic and structured pathing system when dealing with both the Form JSON as well as the Submission JSON objects.

To start, there are now 2 different "types" of paths. Form paths and Data paths. They are defined as follows.

  • Form Path: The path to a component within the Form JSON. This path is used to locate a component provided a nested Form JSON object.

  • Data Path: The path to the data value of a component within the data model for the form. This path is used to provide the value path provided the Submission JSON object.

These paths can also be broken into two different path "types". Local and Full paths.

  • Local Path: This is the path relative to the "current" form. This is used inside of a nested form to identify components and values relative to the current form in context.

  • Full Path: This is the path that is absolute to the root form object. Any nested form paths will include the parent form path as part of the value for the provided path.

These definitions are used within the new "paths" construct which defines the following paths that describe a component.

  • path: The "form" path to the component including all parent paths (exclusive of layout components). This path is used to uniquely identify component within a form inclusive of any parent form paths. For example, a form that has the following component structure (Panel => Form => Panel => Data Grid => Panel => Text Field) would have the following path: form.dataGrid.textField
  • fullPath: The "form" path to the component including all parent paths (inclusive of layout componnts). This path is used to uniquely identify component within a form inclusive of any parent form paths. For example, a form that has the following component structure (Panel => Form => Panel => Data Grid => Panel => Text Field) would have the following path: panel1.form.panel2.dataGrid.panel3.textField
  • localPath: The local "form" path to the component. This is the local path to any component within a form. This path is consistent no matter if this form is nested within another form or not. All form configurations are in relation to this path since forms are configured independently. The difference between a form path and a dataPath is that this includes any parent layout components to locate the component provided a form JSON. This path does NOT include any layout components. For example, a form that has the following component structure (Panel => Form => Panel => Data Grid => Panel => Text Field) would have the following path: dataGrid.textField
  • fullLocalPath: The local "form" path to the component. This is the local path to any component within a form. This path is consistent no matter if this form is nested within another form or not. All form configurations are in relation to this path since forms are configured independently. The difference between a form path and a dataPath is that this includes any parent layout components to locate the component provided a form JSON. This path does NOT include any layout components. For example, a form that has the following component structure (Panel => Form => Panel => Data Grid => Panel => Text Field) would have the following path: panel2.dataGrid.panel3.textField
  • dataPath: The "data" path to the component including all parent paths. This path is used to fetch the data value of a component within a data model, inclusive of any parent data paths of nested forms. For example, a form that has the following component structure (Panel => Form => Panel => Data Grid => Panel => Text Field) would have the following path: form.data.dataGrid[1].textField
  • localDataPath: The "data" path is the local path to the data value for any component. The difference between this path and the "path" is that this path is used to locate the data value for a component within the data model and does not include any keys for layout components. For example, a form that has the following component structure (Panel => Form => Panel => Data Grid => Panel => Text Field) would have the following path: dataGrid[1].textField

Link to Jira Ticket

https://formio.atlassian.net/browse/FIO-8746

Description

This pull requests refactors the "eachComponentData" method to ensure that all of the paths described above are accounted for and can then be used for any component or data references throughout the SDK as well as the renderer.

Breaking Changes / Backwards Compatibility

There are a few things that should be considered "breaking" with this PR.

  1. eachComponent: The callback function for eachComponent receives the "path" parameter as the second parameter to this callback function. This is now the "path" as defined above.

For example.

eachComponent(form.components, function(component, path) {
  console.log(path);  // This is the "path" as defined above.
});
  1. eachComponentData: The callback function for eachComponentData receives a "path" parameter for the third argument to that function. This is now the "dataPath" as defined above.
eachComponentData(form.components, data, function(component, row, path) {
  console.log(path);  // This is the "dataPath" as defined above.
});
  1. "parent" is no longer assigned to the component. With this PR, we are no longer assigning the "parent" property to the component JSON. This is now passed through the iterators and can be referenced there.

Dependencies

None

How has this PR been tested?

New automated tests written.

Checklist:

  • I have completed the above PR template
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (if applicable)
  • My changes generate no new warnings
  • My changes include tests that prove my fix is effective (or that my feature works as intended)
  • New and existing unit/integration tests pass locally with my changes
  • Any dependent changes have corresponding PRs that are listed above

@brendanbond brendanbond merged commit eb1091f into master Dec 9, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants