ui.input_task_button
ui.input_task_button(
id,
label,
*args,
icon=None,
label_busy='Processing...',
icon_busy=MISSING,
width=None,
type='primary',
auto_reset=True,
**kwargs,
)
Creates a button for launching longer-running operations.
Its value is initially zero, and increments by one each time it is pressed. It is similar to input_action_button
, except it prevents the user from clicking when its operation is already in progress.
Upon click, it automatically displays a customizable progress message and disables itself; and after the server has dealt with whatever reactivity is triggered from the click, the button automatically resets to its original appearance and re-enables itself.
In some advanced use cases, it may be necessary to keep a task button in its busy state even after the normal reactive processing has completed. Calling :func:~shiny.ui.update_task_button(id, state = "busy")
from the server will opt out of any currently pending reset for a specific task button. After doing so, the button can be re-enabled by calling update_task_button(id, state = "ready")
after each click's work is complete.
You can also pass an explicit auto_reset = FALSE
to input_task_button()
, which means that button will never be automatically re-enabled and will require update_task_button(id, state = "ready")
to be called each time.
Note that, as a general rule, Shiny's update
family of functions do not take effect at the instant that they are called, but are held until the end of the current reactive cycle. So if you have many different reactive calculations and outputs, you don't have to be too careful about when you call update_task_button(id, state = "ready")
, as the button on the client will not actually re-enable until the same moment that all of the updated outputs simultaneously sent to the client.
Parameters
id : str
-
An input id.
label : TagChild
-
A button label.
*args : TagChild = ()
-
[Experimental] Can be used to add additional states besides “ready” and “busy”. Pass a
span
withslot="state_name"
for each new state, and callupdate_task_button
withstate="state_name"
to switch the button to that state. icon : TagChild = None
-
An icon to appear inline with the button/link.
label_busy : TagChild = 'Processing…'
-
A label to appear when the button is busy.
icon_busy : TagChild | MISSING_TYPE = MISSING
-
An icon to appear inline with the button/link when the button is busy.
width : Optional[str] = None
-
The CSS width, e.g. ‘400px’, or ‘100%’
type : Optional[str] = 'primary'
-
One of the Bootstrap theme colors (‘primary’, ‘default’, ‘secondary’, ‘success’, ‘danger’, ‘warning’, ‘info’, ‘light’, ‘dark’), or None to leave off the Bootstrap-specific button CSS classes. Defaults to ‘primary’.
auto_reset : bool = True
-
Whether to automatically reset the button to “ready” after the task completes. If False, the button will remain in the “busy” state until
update_task_button
is called withstate="ready"
. Also note that even ifauto_reset=True
, callingupdate_task_button
withstate="busy"
will prevent the button from automatically resetting. ****kwargs** : TagAttrValue = {}
-
Attributes to be applied to the button.
Returns
: Tag
-
A UI element
Notes
An integer representing the number of clicks.
See Also
Examples
#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400
## file: app.py
import asyncio
from datetime import datetime
from shiny import App, reactive, render, ui
app_ui = ui.page_fixed(
ui.h5("Current time"),
ui.output_text("current_time"),
ui.p(
"Notice that the time above updates every second, even if you click the button below."
),
ui.layout_sidebar(
ui.sidebar(
ui.input_numeric("x", "x", 1),
ui.input_numeric("y", "y", 2),
ui.input_task_button("btn", "Compute, slowly"),
ui.input_action_button("btn_cancel", "Cancel"),
),
ui.h5("Sum of x and y"),
ui.output_text("show_result"),
),
)
def server(input, output, session):
@render.text
def current_time():
reactive.invalidate_later(1)
return datetime.now().strftime("%H:%M:%S")
@ui.bind_task_button(button_id="btn")
@reactive.extended_task
async def slow_compute(a: int, b: int) -> int:
await asyncio.sleep(3)
return a + b
@reactive.effect
@reactive.event(input.btn, ignore_none=False)
def handle_click():
slow_compute(input.x(), input.y())
@reactive.effect
@reactive.event(input.btn_cancel)
def handle_cancel():
slow_compute.cancel()
@render.text
def show_result():
return str(slow_compute.result())
app = App(app_ui, server)