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

State reactivity bug Form example #444

Open
lukestanley opened this issue Feb 1, 2024 · 4 comments
Open

State reactivity bug Form example #444

lukestanley opened this issue Feb 1, 2024 · 4 comments
Labels

Comments

@lukestanley
Copy link
Member

lukestanley commented Feb 1, 2024

Bug description
Form block fails to update with updated data value. The Form block allows data to pass through on the first use, but the state fails to be reactive after the first use in certain conditions.

form_block_fail_compressed_video.mp4

Reproduction steps

  • Create a Flow with a form block that accepts text input,
  • with a context block saving the input to a namespace,
  • with a mapping block getting the length of the data: length(data),
  • then another mapping block to get the saved input from context,
  • with a second form block with the same schema as the first form.
  • Enter 123 into the first form and press "Submit".
  • You should see the 2nd form be populated by the output of the first form.
  • Modify the value of first form field's text box.
    The user should rightly expect the 2nd form block to be populated by the value from the first form block but it does not.

Expected behaviour
We should expect the Form block to update with the passed in data value.

Flow Configuration:
Flow example link.

Runtime environment:

  • OS: Ubuntu
  • Browser: Firefox 121
  • App version: Production, local development environment
  • Angular Version: 15, 16

Additional context:
The kind of mapping operation appears to matter. The "init" block does seem to change any behaviour. Happens cross-browser: Chrome, Safari and Firefox.

Questions:
Where does the Flow reactivity / re-evaluation break down?
At which block does it stop flowing, and why?
Is the context block to blame? How does using the state system avoid the problem in this flow?
Is the form block needed to reproduce this?
Are two form block's needed?

@lukestanley
Copy link
Member Author

Happy Path Flow

To help understand how the flow operates, when it works correctly, based on my investigations, this is what happens:

graph TD
    A[AppComponent] -->|initiates| B[BlocksWorkflowComponent]
    B -->|reads JSON config| C[InitBlockComponent]
    C -->|first form| D1[FormBlockComponent 1]

    D1 -->|data input| F[ContextSaveBlockComponent saves data to test context]
    F -->|input processed| G1[MappingBlockComponent 1, returns a length of 2]
    G1 -->|second mapping| G2[MappingBlockComponent 2 returns saved context.test]
    G2 -->|second form| D2[FormBlockComponent 2 should be populated by the same as form 1]
    D2 -->|final debug| E2[DebugBlockComponent]
Loading
  • The AppComponent starts the workflow by initiating the BlocksWorkflowComponent based on the URL route.
  • The WorkflowComponent then loads block components based on the Flow's JSON configuration.
  • The process begins with an InitBlockComponent.
  • The first FormBlockComponent is loaded to collect input from the user. It's capable of emitting data right after being loaded and upon form submission.
  • The ContextSaveBlockComponent captures and saves the data for later use in the workflow.
  • Data processing is handled by a MappingBlockComponents, that simply performs a length operation on the input data, outputting the result of 2.
  • The second MappingBlockComponent retrieves the saved data from the context and outputs it.
  • The second FormBlockComponent should by default be pre-populated with the input from above - it should match the above form.
  • A DebugBlockComponent should show the same data.

@lukestanley
Copy link
Member Author

I'm investigating a fix where the execution state of the blocks and data passing could be controlled from the component logic rather than the template renderer's existing big block. I am looking into doing this without async data forking first. So far I have got it outputting the default blocks with no config options used yet, without data passing yet, without using the template, but using a ComponentFactoryResolver. This is good progress. @dahacouk
image
image

@lukestanley
Copy link
Member Author

My dynamic loading investigation is here: 4a516a0 that does not have config being loaded.
I've tried to make config load in a later commit but the effect is not showing.

@lukestanley
Copy link
Member Author

lukestanley commented Mar 14, 2024

image
I've had success setting config and context and I can get some blocks to show with the right config! They do not pass data yet, this would be a good next step I propose.
What was needed was making the block component with createComponent, setting context and config on the instance, and then calling ngOnChanges on the instance. Without the last step nothing was happening, zone.run and markForCheck did not help. SimpleChange was also not needed.
@dahacouk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant