You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I think it would be nice to be able to raise an input event without incrementing a number. To start with it's not an intuitive system, and it would allow for passing values with the event.
It would make lists of items simpler to implement and I think being able to raise arbitrary events from code would be a good feature. It would differ from the current reactive value method in that you could trigger an event for the same value multiple times, currently a change in value is required to trigger a reactive update.
Consider the following test app I made while getting help on Discord:
from shiny import module, reactive, ui, render, Inputs, Outputs, Session, App
from shiny._utils import rand_hex
# ---
# MOCK DATABASE
# ---
# imagine this is a database query result
items = [
"item_1",
"item_2",
"item_3"
]
# this is a function that runs the query
def get_items():
return items
# this function deletes items based on the query
def delete_item(index):
del items[index]
# ---
# ITEM COMPONENT
# ---
@module.ui
def item_ui(item):
return [
ui.markdown(item),
ui.input_action_button("delete_item", "Delete")
]
@module.server
def item_server(input: Inputs, output: Outputs, session: Session, index, on_delete_callback):
@reactive.effect
@reactive.event(input.delete_item, ignore_init=True)
def on_delete():
delete_item(index)
on_delete_callback()
# ---
# MAIN
# ---
app_ui = ui.page_auto(
ui.output_ui("item_list"),
ui.input_action_button("refresh", "Refresh")
)
def app_server(input: Inputs, output: Outputs, session: Session):
items = reactive.value([])
delete_trigger = reactive.value(0)
def on_delete_callback():
delete_trigger.set(delete_trigger.get() + 1)
# this needs to trigger when an item is deleted
# currently we can manually trigger to show that backend is working as intended
@reactive.effect
@reactive.event(input.refresh, delete_trigger, ignore_none=False)
def on_change_items():
# we create a random ID to sync UI and server for each item
items.set([{"item": item, "id": rand_hex(4)} for item in get_items()])
@reactive.effect
def item_servers():
for index, item in enumerate(items.get()):
item_server(item["id"], index, on_delete_callback)
@render.ui
def item_list():
return [item_ui(item["id"], item["item"]) for item in items.get()]
app = App(app_ui, app_server)
Handling the list of items is needlessly unwieldy here. With my proposal you could do this:
from shiny import reactive, ui, render, Inputs, Outputs, Session, App
from shiny._utils import rand_hex
# ---
# MOCK DATABASE
# ---
# imagine this is a database query result
items = [
"item_1",
"item_2",
"item_3"
]
# this is a function that runs the query
def get_items():
return items
# this function deletes items based on the query
def delete_item(index):
del items[index]
# ---
# MAIN
# ---
app_ui = ui.page_auto(
ui.output_ui("item_list"),
ui.input_action_button("refresh", "Refresh")
)
def app_server(input: Inputs, output: Outputs, session: Session):
items = reactive.value([])
# this needs to trigger when an item is deleted
# currently we can manually trigger to show that backend is working as intended
@reactive.effect
@reactive.event(input.refresh, input.delete_item, ignore_none=False)
def on_change_items():
# we create a random ID to sync UI and server for each item
items.set([{"item": item, "id": rand_hex(4)} for item in get_items()])
@render.ui
def item_list():
return [[
ui.markdown(item["item"]),
ui.input_action_button("delete_item", "Delete", value=index)
] for index, item in enumerate(items.get())]
@reactive.effect
@reactive.event(input.delete_item, ignore_init=True)
def on_delete():
# the input will be set to the index to delete by the button click
delete_item(input.delete_item())
app = App(app_ui, app_server)
quite a lot less code and all contained within the UI and server.
In addition to being able to pass values to button events, you could add a function like raise_event("delete_item", i) to be able to trigger on_delete from somewhere else in the server code without needing a reactive.value
The text was updated successfully, but these errors were encountered:
I think it would be nice to be able to raise an input event without incrementing a number. To start with it's not an intuitive system, and it would allow for passing values with the event.
It would make lists of items simpler to implement and I think being able to raise arbitrary events from code would be a good feature. It would differ from the current reactive value method in that you could trigger an event for the same value multiple times, currently a change in value is required to trigger a reactive update.
Consider the following test app I made while getting help on Discord:
Handling the list of items is needlessly unwieldy here. With my proposal you could do this:
quite a lot less code and all contained within the UI and server.
In addition to being able to pass values to button events, you could add a function like
raise_event("delete_item", i)
to be able to triggeron_delete
from somewhere else in the server code without needing areactive.value
The text was updated successfully, but these errors were encountered: