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

FunctionStringVar generates JavaScript exception when provided via a State attribute #4643

Open
bertbarabas opened this issue Jan 15, 2025 · 5 comments

Comments

@bertbarabas
Copy link

bertbarabas commented Jan 15, 2025

Describe the bug
When using a FunctionStringVar to provide a function to the value_formatter of an ag_grid column_def via a State attribute, the value_formatter is ignored and there is a JavaScript exception of:

AG Grid: value should be either a string or a function

If the column_def containing the value_formatter of type FunctionStringVar is instead defined directly in the ag_grid configuration, then the exception doesn't occur and the value_formatter works.

To Reproduce
Just run the following code:
test_reflex_ag_grid.zip

There is a button called "Set columns" which sets the state var and causes the columns to be displayed after the ag_grid is built. You'll see the JavaScript exception in the Browser and you'll note the formatting didn't get applied.

Expected behavior
No exception, and the formatting specified by value_formatter should be applied.

Screenshots
When you first run the code you see:
image

Then you press the "Set columns" button and you see:
image

Note how the Size column does not have the proper formatting (it should have KB and MB suffix as appropriate) and the JavaScript exception on the right.

Specifics (please complete the following information):

  • Python Version: 3.13
  • Reflex Version: reflex=0.6.8 & reflex-ag-grid=0.0.10
  • OS: Windows
  • Browser (Optional): Brave

Additional context
The code provided above was adapted from the working example code below of using a FunctionStringVar to provide a function to the value_formatter of an ag_grid column_def that was provided by @masenf
repro_ag_grid_value_formatter.zip

@masenf
Copy link
Collaborator

masenf commented Jan 15, 2025

When the column_defs prop is coming from a state var (reactive mode), then it doesn't seem to be working with functions defined inline.

As a workaround, you can set the column_defs imperatively from the state, rather than setting columns.

    @rx.event
    def update_columns(self) -> None:
        self.columns = [
            ag_grid.column_def(
                field="path",
                value_formatter=rx.vars.FunctionStringVar(
                    f"(params) => params.value.join({self.separator!r})"  # had to change this line as well
                ),
            ),
            ag_grid.column_def(field="created"),
            ag_grid.column_def(field="modified"),
            ag_grid.column_def(
                field="size",
                value_formatter=rx.cond(
                    self.human_size,
                    human_size,
                    rx.Var.create(None),
                ),
            ),
        ]
        return ag_grid.api("ag_grid_format_1").setGridOption("columnDefs", self.columns)

When the FunctionStringVar is serialized and passed through the call_script interface (used by ag_grid.api), then it turns it into a real function that works as expected.

When the self.columns is serialized and sent to the frontend, it doesn't eval the function definitions.

I don't know if it makes sense to eval FunctionVar from a state, will have to consider it architecturally, but I don't think a specific fix for this is coming any time soon. Let me know if you have any issues with the workaround.

@adhami3310
Copy link
Member

This seems resolved.

@masenf masenf reopened this Jan 30, 2025
@bertbarabas
Copy link
Author

For the record here are some issues with the workaround and how they were resolved;

  1. If when initializing ag_grid I set column_defs=[]
    then afterwards
    return ag_grid.api("ag_grid_format_1").setGridOption("columnDefs", self.columns)
    The columns flash up and then disappear.
    If I leave off the column_def=[] line entirely then the columns display after the setGridOption is called and don't disappear immediately after.
  2. doing a browser refresh won't cause the event to run now that it's explicit. This was resolved by putting the column update event as the on_mount for the grid.
  3. My ag_grid is in a tab. If I leave the tab and come back all columns are forgotten. Triggering the setGridOption when I return to a tab resolves the issue.

@adhami3310
Copy link
Member

I set column_defs=[] then afterwards return ag_grid.api("ag_grid_format_1").setGridOption("columnDefs", self.columns) The columns flash up and then disappear

This is expected to some degree. React derives its state from the component you give to the component and on re-render, these things will be forgotten.

There's an underlying issue though. FunctionVars are not serialized well as props. This is something I should address in my function var PR. In any case, we can add something similar to dynamic component serializer/deserializer such that it knows how to run anonymous functions returned from the backend.

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

No branches or pull requests

3 participants