lowcoder
lowcoder copied to clipboard
[Bug]: Event Handler Action: Control a Component does not work for controls in Modal
Is there an existing issue for this?
- [X] I have searched the existing issues
Current Behavior
When we Event Handler Action Control a Component with method setValue does not work for controls in Modal.
Here is a screenshot for reference.
This same action works if the control is placed on the page but not when placed in a Modal.
Expected Behavior
Actually it should work in all places.
Steps to reproduce
Place a button on page.
Create a Modal and put some input controls there.
On button click event select action Control a Component, select the control placed inside Modal, set Method to setValue and in value field enter a variable name.
Environment
Version 2.4.1
Additional Information
No response
I've been investigating this bug lately, because it was introduced in 2.4.0 and it broke my existing apps after Lowcoder upgrade.
There are at least two bugs related to using setValue on controls inside Modal container.
First one, introduced in commit b0f8e67, which prevents from setting a value to some controls like input (and possibly others) before modal is opened because of useEffect function assigned to defaultValue. This hook resets value to defaultValue when modal is opened, so value from setValue function is overwritten. This was introduced in v2.3.1, but I haven't caught that, as it is quite obscure bug.
Second one, the one you are observing, was introduced with lazy loading comps, in commit 3ab149cf17c36017ad637e7083d092647d9a66b5. This bug was introduced in v2.4.0 and is easier to spot, especially if you use setValue in JS query, because it results in an error toast with setValue is not a function:
Lazy loading removes methods for controls inside modal from eval sandbox, probably because of this line, altough I'm not 100% sure.
If modal is already opened, everything works as it should (both bugs are not present).
I could provide PR for this, but I'm not familiar enough with Lowcoder codebase to properly fix them. @FalkWolsky could you please advise?
As briefly spoken in Discord, we are truly thankful for your research and hint. This will help us to solve the bug faster! Very good.
We had some research, but we cannot confirm that it was ever working to "controlComponent" when this component was placed in a modal and the modal was closed. The reason is that at the moment the Modal is closed, the objects are not instantiated (which makes sense). So, we are wondering if you express this had worked before?
If you checkout commit 11c6dcd (or you can use tag 2.3.0), using setValue appears to be working correctly, altough I'm not sure if this was an intended behaviour.
Here is a demo app, if you first click on setValue button, then Show modal, input1 value will be already changed when modal is opened (i.e. different from it's default value). Demo setValue.json
We had some research, but we cannot confirm that it was ever working to "controlComponent" when this component was placed in a modal and the modal was closed. The reason is that at the moment the Modal is closed, the objects are not instantiated (which makes sense). So, we are wondering if you express this had worked before?
Of course I understand that when modal is closed then its child components could be uninitialized, but it makes it difficult (or unintuitive at least) to prepare controls inside it before it is shown to the user. I am perfectly ok with it staying the way it is in current release as long as there is an other way to achieve the same result (maybe by tieing it to the temporary state, but then what is the purpose of setValue method if sometimes it works, but in other scenarios it does not? ;) ).
Generally "setValue" does also work for Modal - as long as it is displayed. Concepts like setValue are "global" concepts, so they work pretty much everywhere the same. What you found is a special exclusion, just by the standard behaviour of React (which is the foundation as Framework of Lowcoder for Frontend).
If you need to prepare content dynamically in the Modal - isn't then a Module the right way?
Yeah, I think module is the right way to do it, just for simple case, like one or two controls inside modal, this was a convenient way to do it ;)
Anyhow, I think it would be sufficient to mention in the documentation that controls inside modal should not be accessed when modal is hidden and suggest other solutions (like using temporary state or module).
@FalkWolsky As I am rewriting my apps that used this "bug" I think one other way to mitigate this issue is to add an event handler for 'open' event in Modal.
My usecase is following: In my apps I often show user a table with rows of thata and additional column with button Edit. If user clicks it, then editing modal will open up and show a custom form. Because I am often dealing with deeply nested objects from external API and user needs to edit only a few particular properties, I used to use (in versions before 2.3.1 at least ;) ) a JS query that prepopulated controls inside a modal and then showed it to the user. After editing, user clicks on a Submit button inside modal and another JS query propagates new values from controls to the main data structure.
For such apps, making each modal as external module is viable, but adds more boilerplate as this forms are data- and app-specific, so won't be reused in any other place.
If 'open' event handler would be added to the modal, then I can copy user data to temp state variable and assign values to each control in modal after it shows up (which will probably cause some flickering while refreshing data, but will get the job done).
What do you think about it? Maybe this is a wrong design pattern altogether? ;)
The open Event handler is a perfect idea, as we would then stay from the architecture in a good way!
This issue has been dealt by implementing the "Open" Event Handler in this task : https://github.com/lowcoder-org/lowcoder/pull/1132. So, we don't need this ticket anymore.