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

FIO-9241: Correctly set current page after conditionally hiding page in sibling nested wizard #5913

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

Conversation

blakekrammes
Copy link
Contributor

@blakekrammes blakekrammes commented Nov 18, 2024

Link to Jira Ticket

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

Description

What changed?

I updated the onChange() method in the Wizard class to call this.setPage() if the number of total pages in the parent/root-level wizard changes, which updates the current page of the root wizard to be the current page/page (i.e. this.currentPanel. this.setPage() was not being called onChange() for wizards with sub-wizards. I also updated render() to set this.currentPanel based on id and not key.

Why have you chosen this solution?

I changed onChange() in the way that I did to simplify the logic for when to set the current page and to ensure that the correct page is selected based on a (more) unique id and not key, which could be easily duplicated between sub-wizard pages.

For the update to render(), I made that change since another bug manifested where pages in multiple sub-wizards having the same key would cause the current page to jump from one sub-wizard to another. (i.e. B2 to C2) when A2 was conditionally hidden by the value of B2 because both B2 and C2 have the same key of (I think) 'page2'. A2 being a page of sub-wizard form A, and the same for pages B2 and C2, in respect to the sub-wizards B and C.

Breaking Changes / Backwards Compatibility

I removed this.currentPanels from the Wizard class in order to simplify the logic in onChange() since the current Wizard pages/panels (including those of all sub-wizards) can be accessed via this.pages. This might break something, but I'm not sure of a case where it would. All of the tests pass with it removed. See this comment for more details.

Dependencies

n/a

How has this PR been tested?

Manual and automated testing.

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

- The getter had more nuanced logic in the past, but now only checks if the wizard form has sub/nested wizards
@@ -216,9 +215,9 @@ export default class Wizard extends Webform {
render() {
const ctx = this.renderContext;

if (this.component.key) {
if (this.component.id) {
Copy link
Contributor Author

@blakekrammes blakekrammes Nov 20, 2024

Choose a reason for hiding this comment

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

There was an additional bug here:

If you had multiple/sibling nested wizards and conditional logic controlling the visibility of a nested wizard page, this was setting the currentPanel to the wrong page on render (i.e. both forms have a 'page1' key and the wizard would navigate to 'page1' on nested form C instead of 'page1' on nested form B. This is fixed by using a unique id to set the currentPanel.

- If you have multiple/sibling nested wizards and conditional logic controlling the visibility of a nested wizard page, it can set the currentPanel to the wrong page on render (i.e. both forms have a 'page1' key. This is fixed by using a unique id to set the currentPanel.
- this.setPage wasn't being called after conditional logic was evaluated on the page of a nested wizard form having a sibling nested wizard form, causing the main wizard page index not to update to the correct page
- Clean up onChange logic
  - this.currentPanels was only being referenced in onChange() and didn't seem like a necessary piece of state in addition to this.pages
@blakekrammes blakekrammes changed the title WIP: reset current page when nested wizards exist and page is conditi… WIP: reset current page when nested wizards exist and page is conditionally hidden Nov 21, 2024
@blakekrammes blakekrammes changed the title WIP: reset current page when nested wizards exist and page is conditionally hidden Correctly set page after conditionally hiding page in sibling nested wizard Nov 21, 2024
}
else {
currentPanels = this.currentPanels || this.pages.map(page => page.component.key);
Copy link
Contributor Author

@blakekrammes blakekrammes Nov 21, 2024

Choose a reason for hiding this comment

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

this.currentPanels was only referenced within onChange and seems like an unnecessary piece of state given that the current pages/panels can be accessed via this.pages. I could be missing/unaware of a case, but all the tests pass happily without it and I really wanted to simplify this logic.

From what I can tell, this.currentPanels was only tracking the parent pages, which in the case of a wizard having nested wizards forms A, B and C, would only return the top-level parent pages for those forms. However, that's not useful when you're trying to update the current page to a particular page in one of those nested forms. I don't believe it's possible to navigate to a parent page A without expanding its children and selecting the first page A1. this.pages is a flattened array and stores every page in every nested wizard and can be used to select the correct page after onChange is called for both simple, single-level wizards, and wizards with nested wizards.

I think the reason why this.currentPanels worked for selecting the current page in single-level wizards was because the top-level panel components are navigable pages. However, when you have nested wizards, they are not navigable pages.

For comparison:

this.currentPanels = [{ title: 'A', ... }, { title: 'B', ... }, { title: 'C', ... }]
this.pages = [{ title: 'A1', ... }, { title: 'A2', ... },  { title: 'A3', ... }, { title: 'B1', ... }, ...]

@blakekrammes blakekrammes marked this pull request as ready for review November 21, 2024 23:05
ctx.panels.map(panel => {
if (panel.key === this.component.key) {
if (this.component.id) {
ctx.panels.forEach(panel => {
Copy link
Contributor Author

@blakekrammes blakekrammes Nov 22, 2024

Choose a reason for hiding this comment

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

.forEach is more appropriate since we're applying side-effects and not returning a new array.

@blakekrammes blakekrammes changed the title Correctly set page after conditionally hiding page in sibling nested wizard Correctly set current page after conditionally hiding page in sibling nested wizard Nov 22, 2024
@blakekrammes blakekrammes changed the title Correctly set current page after conditionally hiding page in sibling nested wizard FIO-9241: Correctly set current page after conditionally hiding page in sibling nested wizard Nov 22, 2024
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.

1 participant