Open shebdon opened 10 months ago
Here's a module and usage for teh workaround.
from shiny import module, ui, reactive, render
@module.ui
def controlled_numeric_ui():
return ui.output_ui("numeric")
@module.server
def controlled_numeric_server(input, output, session, my_id:str = "controlled_number", my_label:str = "Can't type out-of-range number", my_value:float = 1, my_min:float = 1, my_max:float=100):
@output
@render.ui
def numeric():
return ui.input_numeric("controlled_numeric", label=my_label, value=my_value, min=my_min, max=my_max)
@reactive.Effect
def _():
if not isinstance(input.controlled_numeric(), int):
return
if input.controlled_numeric() > my_max :
ui.update_numeric("controlled_numeric", label=my_label, value=my_max, min = my_min, max = my_min)
if input.controlled_numeric() < my_min :
ui.update_numeric("controlled_numeric", label=my_label, value=my_min, min = my_min, max = my_min)
return input.controlled_numeric
And here's a usage example:
from shiny import App, Inputs, Outputs, Session, ui, render
from numeric_module import controlled_numeric_server, controlled_numeric_ui
app_ui = ui.page_fluid(
controlled_numeric_ui("numeric_module"),
ui.output_text_verbatim("value")
)
def server(input: Inputs, output: Outputs, session: Session):
controlled_value = controlled_numeric_server("numeric_module",my_id="controlled_value", my_label="Forced to be in range", my_value=10, my_min=1, my_max=100)
@output
@render.text
def value():
return controlled_value()
app = App(app_ui, server)
ui.input_numeric does not currently catch/correct typed values outside of the min/max range (aka min/max range arguments are ineffective for typed user input).
This can be reproduced using the example here: https://shiny.posit.co/py/api/ui.input_numeric.html when the user types in 1000, the server responds with 1000, even though the max is set to 100.
The expected functionality can be simulated with the app below. When the users enters an out-of-bounds value, it is imediately replaced with the nearest within-bounds value. With modules, one can build their own control system, though this feels like unintented behavior of the ui.input_numeric function.
Thanks,