How to press "Enter" on TextInput to trigger a Button?

import panel as pn
pn.extension()

text = pn.widgets.TextInput()
button = pn.widgets.Button()
pn.Column(text, button).servable()

One way is to watch the param “value” change, but that can be triggered from other than “Enter”.

Use case is two text inputs (user / pass) and button (submit). When user clicks enter on the password text input, it triggers validation.

Maybe something like this?

import panel as pn
pn.extension()

text = pn.widgets.TextInput(placeholder="Username")
button = pn.widgets.Button(name="Submit")
button.on_click(lambda x: print("Button"))

@pn.depends(text, watch=True)
def test(t):
    print("Text:", t)
    button.clicks += 1

pn.Column(text, button).servable()

Thanks. If you click away, it automatically presses submit which I don’t want:

import time
import panel as pn
pn.extension()

text = pn.widgets.TextInput(placeholder="Username")
button = pn.widgets.Button(name="Submit")
button.on_click(lambda x: print("Button"))

@pn.depends(text, watch=True)
def test(t):
    print("Text:", t)
    button.clicks += 1
    button.loading = True
    time.sleep(1)
    button.loading = False

pn.Column(text, button).servable()

I tried playing around with ReactiveHTML (for the first time) and got something to work. It is in no way perfect but I think it is a good starting point.

import param
import panel as pn


# Inspiration:
# https://www.w3schools.com/howto/howto_css_login_form.asp
# https://stackoverflow.com/questions/25983603/how-to-submit-an-html-form-without-redirection
# https://panel.holoviz.org/user_guide/Custom_Components.html


RAW_CSS = """
body {font-family: Arial, Helvetica, sans-serif;}
form {border: 3px solid #f1f1f1;}

input[type=text], input[type=password] {
  width: 100%;
  padding: 12px 20px;
  margin: 8px 0;
  display: inline-block;
  border: 1px solid #ccc;
  box-sizing: border-box;
}

button {
  background-color: #04AA6D;
  color: white;
  padding: 14px 20px;
  margin: 8px 0;
  border: none;
  cursor: pointer;
  width: 100%;
}

button:hover {
  opacity: 0.8;
}
"""
pn.config.raw_css.append(RAW_CSS)


class Login(pn.reactive.ReactiveHTML):
    username = param.String()
    password = param.String()
    logged_in = param.Boolean()

    _template = """
    <iframe name="dummyframe" id="dummyframe" style="display: none;"></iframe>
    <form target="dummyframe">
        <input id="username" type="text" value="${username}" placeholder="Username" required></input>
        <input id="password" type="password" value="${password}" placeholder="Password" required></input>
        <button id="button" onclick="${_validates_login}">Login</button>
    </form>

    <div id="login">${logged_in}</div>
    """
    _dom_events = {"username": ['change'], "password": ['change']}

    def _validates_login(self, *events):
        if self.username == "s" and self.password == "s":
            self.logged_in = True
        else:
            self.logged_in = False

        print(self.logged_in)

        return False


Login().servable()

Some problems which needs to be ironed out:

  • The fields gives a Bokeh error when I insert numbers only.
  • Sometimes I have to press double enter to get the login to work.
  • Be sure that there isn’t any security risks or similar.
2 Likes