pythonpy-shiny

How to make a reactive event silent for a specific function?


I have the app at the bottom. Now, I have this preset field where I can select from 3 options (+ the option changed). What I want to be able to set the input_option with the preset field. But I also want to be able to change it manually. If I change the input_option manually the preset field should switch to changed. The problem is, if I set the option with the preset field, this automatically triggers the second function and sets input_preset back to changed. But this should only happen, if I manually change it, not if it is changed by the first reactive function. is that somehow possible? I tried a little with reactive.isolate(), but this does not seem to have any effect.

from shiny import App, ui, reactive


app_ui = ui.page_fillable(
    ui.layout_sidebar(
        ui.sidebar(
            ui.input_select("input_preset", "input_preset", choices=["A", "B", "C", "changed"]),
            ui.input_text("input_option", "input_option", value=''),
        )
    )
)


def server(input, output, session):


    @reactive.effect
    @reactive.event(input.input_preset)
    def _():
        if input.input_preset() != 'changed':
            # with reactive.isolate():
                ui.update_text("input_option", value=str(input.input_preset()))


    @reactive.effect
    @reactive.event(input.input_option)
    def _():
        ui.update_select("input_preset", selected='changed')


app = App(app_ui, server)


Solution

  • Require (req()) input.input_option() != input.input_preset() for doing the update on the preset input:

    from shiny import App, ui, reactive, req
    
    app_ui = ui.page_fillable(
        ui.layout_sidebar(
            ui.sidebar(
                ui.input_select("input_preset", "input_preset", choices=["A", "B", "C", "changed"]),
                ui.input_text("input_option", "input_option", value=''),
            )
        )
    )
    
    def server(input, output, session):
    
        @reactive.effect
        @reactive.event(input.input_preset)
        def _():
            if input.input_preset() != 'changed':
                ui.update_text("input_option", value=str(input.input_preset()))
    
        @reactive.effect
        @reactive.event(input.input_option)
        def _():
            req(input.input_option() != input.input_preset())
            ui.update_select("input_preset", selected='changed')
    
    app = App(app_ui, server)