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

Button name not updated when using reactive expression #6426

Closed
Tracked by #6425
MarcSkovMadsen opened this issue Mar 3, 2024 · 3 comments
Closed
Tracked by #6425

Button name not updated when using reactive expression #6426

MarcSkovMadsen opened this issue Mar 3, 2024 · 3 comments
Labels
type: bug Something isn't correct or isn't working
Milestone

Comments

@MarcSkovMadsen
Copy link
Collaborator

panel==1.3.8

I'm working on the Basic tutorials. I'm trying to explain a watch like pattern. I don't yet know if this is possible.

To get some rough, proxy example working I tried the below.

import panel as pn

pn.extension()

submit = pn.widgets.Button(name="Start the wind turbine")

def start_stop_wind_turbine(clicked):
    print(clicked, submit.clicks)
    if bool(submit.clicks%2):
        submit.name="Start the wind turbine"
    else:
        submit.name="Stop the wind turbine"
    return None

rx_start_stop_windturbine = pn.rx(start_stop_wind_turbine)(submit)

# Figure out how to watch

pn.Column(submit, pn.panel(rx_start_stop_windturbine)).servable()

But it did not behave as expected. As you can see it updates one of the submit buttons only when clicked.

not-updating.mp4

I would expect both Buttons to have their name updated when one of the buttons is clicked.

@MarcSkovMadsen MarcSkovMadsen added the type: bug Something isn't correct or isn't working label Mar 3, 2024
@MarcSkovMadsen MarcSkovMadsen added this to the next milestone Mar 3, 2024
@MarcSkovMadsen
Copy link
Collaborator Author

A additional problem is seen in this example

import asyncio
import concurrent.futures
from time import sleep

import panel as pn

pn.extension()

is_stopped=pn.rx(True)
is_active = pn.rx(False)

def name(stopped):
    if stopped:
        return "Start the wind turbine"
    else:
        return "Stop the wind turbine"

rx_name = pn.rx(name)(is_stopped)

submit = pn.widgets.Button(name=rx_name, disabled=is_active, loading=is_active)

async def start_stop_wind_turbine(clicked):
    if not clicked:
        return
    is_active.rx.value=True
    with submit.param.update(loading=True, disabled=True):
        with concurrent.futures.ThreadPoolExecutor() as executor:
            future = executor.submit(sleep, 5)
            result = await asyncio.wrap_future(future)

        is_stopped.rx.value = not is_stopped.rx.value
    is_active.rx.value=False
    print("done")


b_stop_wind_turbine = pn.rx(start_stop_wind_turbine)(submit)

# Todo: Fix same problems as in Watch section

pn.Column(submit, b_stop_wind_turbine).servable()

Besides the original button not reacting we now have the problem that the rx button never gets enabled again.

not-stopping.mp4

@philippjfr
Copy link
Member

I would very much like to discourage what you're doing in the first example.

The most concise way to write that example is this:

import panel as pn

pn.extension()

submit = pn.widgets.Button(name="Start the wind turbine")

submit.name = (submit.param.clicks.rx() % 2).rx.where("Start the wind turbine", "Stop the wind turbine")

submit.servable()

but I can appreciate that's not obvious. And I do appreciate that you might want to watch a expression and that can also be done already:

submit = pn.widgets.Button(name="Start the wind turbine")

def update_button(active):
    submit.name = "Start the wind turbine" if active else "Stop the wind turbine"

(submit.param.clicks.rx() % 2).rx.watch(update_button)

pn.Row(submit)

In your second example, everything works fine if you remove with submit.param.update(loading=True, disabled=True), which is superfluous. That does represent a Param issue though since the context manager should restore the parameter reference.

@philippjfr
Copy link
Member

Between your issue holoviz/param#913 and my issue holoviz/param#914 and the fact that .param.watch exists for the callback based use case I think all issues here are covered.

@philippjfr philippjfr modified the milestones: next, v1.4.0 Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't correct or isn't working
Projects
None yet
Development

No branches or pull requests

2 participants