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

Unable to build form with submit button from HTML #1770

Open
thohan88 opened this issue Nov 13, 2024 · 1 comment
Open

Unable to build form with submit button from HTML #1770

thohan88 opened this issue Nov 13, 2024 · 1 comment

Comments

@thohan88
Copy link

This may be intentional as I seem to remember there being some issues with submit buttons in shiny for R.

My use case was just a simple form POST with action attached, and I expected this to work:

from shiny import App, ui
from htmltools import HTML

app_ui = ui.page_auto(
    ui.h2("Login"),
    HTML(
        """
         <form action="/api/auth/web/login" method="POST">
            <input type="email" id="username" name="username">
            <input type="password" id="password" name="password">
            <button type="submit" class="btn btn-primary">Login</button>
        </form>
        """
    ),
)

def server(input, output, session):
    pass

app = App(app_ui, server)

Nothing happens when the button is clicked, and I can't find the cause. A pure HTML file seems to work fine:

<!DOCTYPE html>
<html>
    <body>
        <form action="/api/auth/web/login" method="POST">
            <input type="email" id="username" name="username">
            <input type="password" id="password" name="password">
            <button type="submit" class="btn btn-primary">Login</button>
        </form>
    </body>
</html>
@thohan88
Copy link
Author

After looking further into this, I realize this may be the intended behavior:
https://github.com/rstudio/shiny/blob/501b012b2b82c0c468dc921ff0a3d9a682c20623/srcts/src/shiny/index.ts#L179-L192

For anyone stumbling on this, you can override the "inputsDefer"-behavior for submit buttons with some javascript:

document.addEventListener('DOMContentLoaded', function() {
    document.getElementById('loginSubmit').addEventListener('click', function(event) {
        document.getElementById('loginForm').submit();
    });
});

So the following works:

from shiny import App, ui
from htmltools import HTML

# JavaScript to handle form submission via button click
# Overrides https://github.com/rstudio/shiny/blob/501b012b2b82c0c468dc921ff0a3d9a682c20623/srcts/src/shiny/index.ts#L179-L192
js = """
document.addEventListener('DOMContentLoaded', function() {
    document.getElementById('loginSubmit').addEventListener('click', function(event) {
        document.getElementById('loginForm').submit();
    });
});
"""

app_ui = ui.page_auto(
    ui.h2("Login"),
    ui.head_content(ui.tags.script(js)),
    HTML(
        """
        <form action="/api/auth/web/login" method="POST" id="loginForm">
            <input type="email" id="username" name="username">
            <input type="password" id="password" name="password">
            <button type="button" class="btn btn-primary" id="loginSubmit">Login</button>
        </form>
        """
    ),
)

def server(input, output, session):
    pass

app = App(app_ui, server)

I am currently experimenting with combining FastAPI and Shiny. In my specific case, the FastAPI endpoint /api/auth/web/login sets a cookie upon successful authentication which gates access to another shiny app. This simple login app could of course be a static page, but I tried to quickly mock something up with shiny. Curious to hear if anyone has advice on a better approach. Otherwise, feel free to close this issue.

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

No branches or pull requests

1 participant