I'm having an issue with a Shiny application with nested navs, and a plotly figure using shinywidgets. Because the issue only (?) occurs when nested navs are involved, I suspect this is a shiny issue, and not a shinywidgets issue.
I have narrowed down the problem to the following sample program.
The app is constructed as a page_navbar, with 2 tabs, "Nav A" and "Nav B".
"Nav A" is built as a navset_tab with two subtabs, "SubNav A" and "SubNav B". "SubNav A" contains a first output_widget, i.e. this is an output_widget on level 2 of the nav tree.
"Nav B" is containing a second output_widget. This is an output_widget on level 1 of the nav tree.
The weird thing is that the first output_widget (level 2) is only displayed if the second output_widget (level 1) exists.
If I comment out the second output_widget, the first one is not rendered.
The second output_widget doesn't even need to be rendered. Just having the output_widget in the ui is enough to be able to render the first one.
Here's a sample program demonstrating the issue (you need to play with comments on the output_widget from Section 2).
from shiny import *
from shinywidgets import *
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
df = pd.DataFrame(np.random.randn(50, 3), index=range(50), columns=["x", "y", "z"])
# App consists of a top navigation bar, with 2 navigation items "Nav A" and "Nav B"
app_ui = ui.page_navbar(
ui.nav(
"Nav A",
# Section 1 : nested navset, with one nav containing an output_widget
# This only renders correctly if there's an output_widget in the "Nav B" tab
ui.navset_tab(
ui.nav("SubNav A",
ui.h3("Plotly widget 1"),
output_widget("out_plotly_widget1"),
),
ui.nav("SubNav B")
),
),
ui.nav(
"Nav B",
# Section 2 : the output_widget must exist for the first output_widget (above) to render
ui.h3("Plotly widget 2"),
output_widget("out_plotly_widget2"),
),
ui.nav_control(
ui.input_select("in_selection", label=None, choices=[1,2,3,4])
),
)
def server(input, output, session):
selected_value = reactive.Value()
@reactive.Effect
def _():
req(input.in_selection())
selected_value.set(input.in_selection())
@output
@render_widget
def out_plotly_widget1():
fig = px.scatter(df, x="x", y="y")
return go.FigureWidget(fig)
# Only for illustrative reasons.
# Doesn't make a difference if this rendering function exists or not
# Can be commented out without any impact
@output
@render_widget
def out_plotly_widget2():
fig = px.scatter(df, x="y", y="z")
return go.FigureWidget(fig)
app = App(app_ui, server)
So this works :
Section 1 + Section 2
This doesn't work :
Section 1 ( Section 2 commented out)
In a further test, I also inluded a navset_tab for "Nav B". It appears that it's not enough to have an output widget defined on level 2.
There needs to be a widget on level 1 (dummy or not).
In the following code snippet, I moved out_plotly_widget_2 one level down, and added a dummy widget in "Nav B".
from shiny import *
from shinywidgets import *
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
df = pd.DataFrame(np.random.randn(50, 3), index=range(50), columns=["x", "y", "z"])
# App consists of a top navigation bar, with 2 navigation items "Nav A" and "Nav B"
app_ui = ui.page_navbar(
ui.nav(
"Nav A",
# Section 1 : nested navset, with one nav containing an output_widget
# This only renders correctly if there's an output_widget in the "Nav B" tab
ui.navset_tab(
ui.nav("SubNav AA",
ui.h3("Plotly widget 1"),
output_widget("out_plotly_widget1"),
),
ui.nav("SubNav AB")
),
),
ui.nav(
"Nav B",
# Section 2 : the output_widget must exist for the first output_widget (above) to render
ui.navset_tab(
ui.nav("SubNav BB",
ui.h3("Plotly widget 2"),
output_widget("out_plotly_widget2"),
),
ui.nav("SubNav BB")
),
# ui.h3("Dummy widget"),
output_widget("dummy widget"),
)
)
def server(input, output, session):
selected_value = reactive.Value()
@reactive.Effect
def _():
req(input.in_selection())
selected_value.set(input.in_selection())
@output
@render_widget
def out_plotly_widget1():
fig = px.scatter(df, x="x", y="y")
return go.FigureWidget(fig)
# Only for illustrave reasons.
# Doesn't make a difference if this rendering function exists or not
# Can be commented out without any impact
@output
@render_widget
def out_plotly_widget2():
fig = px.scatter(df, x="y", y="z")
return go.FigureWidget(fig)
app = App(app_ui, server, debug=True)
It doesn't seem to matter where you put the dummy widget (Nav A or Nav B).
Hello,
I'm having an issue with a Shiny application with nested navs, and a plotly figure using shinywidgets. Because the issue only (?) occurs when nested navs are involved, I suspect this is a shiny issue, and not a shinywidgets issue.
I have narrowed down the problem to the following sample program. The app is constructed as a page_navbar, with 2 tabs, "Nav A" and "Nav B". "Nav A" is built as a navset_tab with two subtabs, "SubNav A" and "SubNav B". "SubNav A" contains a first output_widget, i.e. this is an output_widget on level 2 of the nav tree. "Nav B" is containing a second output_widget. This is an output_widget on level 1 of the nav tree.
The weird thing is that the first output_widget (level 2) is only displayed if the second output_widget (level 1) exists. If I comment out the second output_widget, the first one is not rendered. The second output_widget doesn't even need to be rendered. Just having the output_widget in the ui is enough to be able to render the first one.
Here's a sample program demonstrating the issue (you need to play with comments on the output_widget from Section 2).
So this works :
This doesn't work :
In a further test, I also inluded a navset_tab for "Nav B". It appears that it's not enough to have an output widget defined on level 2. There needs to be a widget on level 1 (dummy or not).
In the following code snippet, I moved out_plotly_widget_2 one level down, and added a dummy widget in "Nav B".
It doesn't seem to matter where you put the dummy widget (Nav A or Nav B).
So there seems to be a workaround ...
Thanks for having a look.
Bart