zauberzeug / nicegui

Create web-based user interfaces with Python. The nice way.
https://nicegui.io
MIT License
10.2k stars 607 forks source link

Binding confirmation button to text input #3970

Closed rodrigovillarbello closed 2 weeks ago

rodrigovillarbello commented 2 weeks ago

Description

I am trying to implement a simple text input plus confirmation button in a dialog, where the button is only enabled if the input validation is passed:

my_input = ui.input(label = 'test', validation = {
    'empty error': lambda m: m.strip() != '',
    'other error': lambda m: len(m.strip()) != 3
}).props('autofocus')

confirm_button = ui.button('confirm').bind_enabled_from(my_input, 'error', lambda error: error is None)

The only problem with this code is that the button is enabled right after the page is loaded and the input is blank (because the user has not typed anything yet), which is something I don't want to happen as you can see in the validation dictionary.

What I have tried:

  1. confirm_button.disable() or confirm_button.set_enabled(False) do nothing. I guess this is because the binding has prevalence over these functions, and my_input.error is None when the page is loaded, so the binding makes the button enabled.

  2. Manually setting my_input.error = 'empty error' works and it makes the button start disabled, but it also shows the error styling on the input right after the page is loaded. I would like to avoid this since I don't really like the idea of showing the user an error when it hasn't typed anything yet.

  3. I saw at https://github.com/zauberzeug/nicegui/discussions/2621 that I could also use confirm_button.props('disable'), but even though the button now starts disabled, it doesn't get enabled until it has failed the validation at least one time. For example, given the second validation rule shown above:

    • The page loads, and the button is disabled because of the props.
    • The user types letter a, and the button is still disabled even though it shouldn't. The input shows no error styling.
    • The user types letter b, and the button is still disabled even though it shouldn't. The input shows no error styling.
    • The user types letter c, and the button is still disabled, which it should since the input is now 3 characters long. The input now also shows its error styling.
    • The user types/deletes any letter, and the button is finally enabled.

I believe I can make this work by manually enabling and disabling the button after checking if the input is valid using an on_change callback, but I would like to know if there are other ways to approach this. Also, I don't know if this last behaviour is some sort of bug, but it seems it works the same way on versions 2.0.0 and 2.5.0.

Thank you.