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

[REF-2745] rx.form handle_submit lambda cannot reference foreach vars #3210

Open
masenf opened this issue May 1, 2024 · 0 comments
Open
Labels
bug Something isn't working Hosting Bug Created by Linear-GitHub Sync

Comments

@masenf
Copy link
Collaborator

masenf commented May 1, 2024

Describe the bug
When rendering a form inside an rx.foreach, the value and index of the loop are not available to an on_submit lambda function.

To Reproduce

import reflex as rx


class State(rx.State):
    def handle_submit(self, index, form_data):
        print(f"Form data for index {index}: {form_data}")


def index() -> rx.Component:
    return rx.vstack(
        rx.foreach(
            rx.Var.range(3),
            lambda index: rx.form(
                rx.hstack(
                    rx.input(name="input", placeholder=f"Input {index}"),
                    rx.button("Submit"),
                ),
                on_submit=lambda form_data: State.handle_submit(index, form_data),
            ),
        ),
    )


app = rx.App()
app.add_page(index)

Expected behavior
The event handler is called with the appropriate loop index.

Instead I get a frontend error.

Screenshots

image

Unhandled Runtime Error
ReferenceError: index is not defined

Source
pages/index.js (47:61) @ index

  45 | const form_data = {...Object.fromEntries(new FormData($form).entries()), ...{}}
  46 |
> 47 | addEvents([Event("state.state.handle_submit", {index:index,form_data:form_data})])
     |                                                     ^
  48 |
  49 | if (false) {
  50 |     $form.reset()

The following JS is generated

export function Flex_b1f247bd60753a6b989f5a0a615461c8 () {
  const [addEvents, connectErrors] = useContext(EventLoopContext);


  
    const handleSubmit_a38fe166b30dfd298368c2a885298234 = useCallback((ev) => {
        const $form = ev.target
        ev.preventDefault()
        const form_data = {...Object.fromEntries(new FormData($form).entries()), ...{}}

        addEvents([Event("state.state.handle_submit", {index:index,form_data:form_data})])

        if (false) {
            $form.reset()
        }
    })
    

  return (
    <RadixThemesFlex align={`start`} className={`rx-Stack`} direction={`column`} gap={`3`}>
  {Array.from(range(3, undefined, 1)).map((index, index_a81095fb6a95165312c0dc2039761a49) => (
  <RadixFormRoot className={`Root`} key={index_a81095fb6a95165312c0dc2039761a49} onSubmit={handleSubmit_a38fe166b30dfd298368c2a885298234}>
  <RadixThemesFlex align={`start`} className={`rx-Stack`} direction={`row`} gap={`3`}>
  <RadixThemesTextField.Root name={`input`} placeholder={`Input ${index}`}/>
  <RadixThemesButton>
  {`Submit`}
</RadixThemesButton>
</RadixThemesFlex>
</RadixFormRoot>
))}
</RadixThemesFlex>
  )
}

As you can see, the index var is out of scope in the externalized handleSubmit_a38fe166b30dfd298368c2a885298234 callback.

Specifics (please complete the following information):

  • Python Version: 3.11.8
  • Reflex Version: 0.4.9 / main
  • OS:
  • Browser (Optional):

Workaround

Creating an rx.el.input(type="hidden") and pass the value via the form_data does work, but it's less clean.

From SyncLinear.com | REF-2745

@masenf masenf changed the title rx.form handle_submit lambda cannot reference foreach vars [REF-2745] rx.form handle_submit lambda cannot reference foreach vars May 1, 2024
@masenf masenf added bug Something isn't working Hosting Bug Created by Linear-GitHub Sync labels May 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working Hosting Bug Created by Linear-GitHub Sync
Projects
None yet
Development

No branches or pull requests

1 participant