I have the following Shiny for Python app that I want to execute where the app starts with a simple welcome page that asks for a value, with a button that the user clicks on when complete. After the button is clicked, a new page renders with a ui.page_navbar
layout (including the text value entered at the welcome page).
Here is the code:
from shiny import App, ui, reactive, render
# main ui object for the app
app_ui = ui.page_fluid(
ui.div(
( "Welcome Screen",
ui.input_text(id='str_val', label='Type in something'),
ui.input_action_button(id="btn_welcome", label="Proceed!"),
),
id="welcome_screen",
),
ui.div(id="main_page")
)
# main server function for the app
def server(input, output, session):
@reactive.effect
@reactive.event(input.btn_welcome, ignore_init=True, ignore_none=True)
def _():
ui.remove_ui(selector="div:has(> #welcome_screen)")
ui.insert_ui(
selector=f"#main-page",
where="beforeBegin",
ui= ui.page_navbar(
ui.nav_panel("Tab 1", "Tab 1 content",ui.output_text('str_val')),
ui.nav_panel("Tab 2", "Tab 2 content"),
ui.nav_panel("Tab 3", "Tab 3 content"),
title="Main Page",
id="page",
),
)
@render.text
def str_val():
return input.str_val()
app = App(app_ui, server)
When I run this, the welcome screen loads and works as expected. When I click on the button, the welcome screen disappears, but then the screen is blank, the ui.page_navbar
layout doesn't appear. I have successfully used ui.insert_ui
to place content within a div before successfully, but for some reason it isn't working with a page_navbar type tag. I thought maybe the issue was that a ui.page_navbar
object couldn't be placed inside a div (where I'm trying to insert it using ui.insert_ui
), but in a separate test I was able to do that by just placing it in the app_ui code manually.
The one point is that the selector within the ui.insert_ui
contains a typo, you can change it to main_page
instead of main-page
such that it matches what is defined in the ui
.
The other thing is that ui.remove_ui(selector="div:has(> #welcome_screen)")
also removes the main_page
div (see the MDN docs on :has()
) and then ui.insert_ui
with selector=f"#main_page"
can't find where to insert the ui
. Instead, you can delete the welcome screen by just using ui.remove_ui("#welcome_screen")
.
Putting it together, a complete minimal example could be written like this:
from shiny import App, ui, reactive, render
# main ui object for the app
app_ui = ui.page_fluid(
ui.div(
( "Welcome Screen",
ui.input_text(id='str_val', label='Type in something'),
ui.input_action_button(id="btn_welcome", label="Proceed!"),
),
id="welcome_screen",
),
ui.div(id="main_page")
)
# main server function for the app
def server(input, output, session):
@reactive.effect
@reactive.event(input.btn_welcome, ignore_init=True, ignore_none=True)
def _():
ui.remove_ui("#welcome_screen")
ui.insert_ui(
selector=f"#main_page",
where="beforeBegin",
ui= ui.page_navbar(
ui.nav_panel("Tab 1", "Tab 1 content",ui.output_text('str_val')),
ui.nav_panel("Tab 2", "Tab 2 content"),
ui.nav_panel("Tab 3", "Tab 3 content"),
title="Main Page",
id="page",
),
)
@render.text
def str_val():
return input.str_val()
app = App(app_ui, server)