Shiny Modules
Not to be confused with a Python Module
Shiny modules
Share a few tips, tricks, and “code smells” for using Shiny modules
Shiny modules:
- Namespaceing (isolation)
- Reuse code (just like a normal function)
- Do not need to worry about duplicate IDs as you reuse modules
Similar to a normal function
- Inputs and outputs (not to be confused with Shiny inputs and outputs)
Motivation


Code smell - Repeated elements
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
from shiny import App, ui
app_ui = ui.page_fluid(
ui.input_slider("n1", "N", 0, 100, 20),
ui.input_slider("n2", "N", 0, 100, 20),
ui.input_slider("n3", "N", 0, 100, 20),
ui.input_slider("n4", "N", 0, 100, 20),
ui.input_slider("n5", "N", 0, 100, 20),
ui.input_slider("n6", "N", 0, 100, 20),
)
app = App(app_ui, None)
Code smell - multiple function calls
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
from shiny import App, ui
def my_slider(id):
return ui.input_slider(id, "N", 0, 100, 20)
app_ui = ui.page_fluid(
my_slider("n1"),
my_slider("n2"),
my_slider("n3"),
my_slider("n4"),
my_slider("n5"),
)
app = App(app_ui, None)
Code smell - UI via list iteration
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
from shiny import App, ui
def my_slider(id):
return ui.input_slider(id, "N", 0, 100, 20)
ids = ["n1", "n2", "n3", "n4", "n5"]
app_ui = ui.page_fluid([my_slider(x) for x in ids])
app = App(app_ui, None)
Code smell - iterating over multiple lists
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
from shiny import App, ui
def my_slider(id, label):
return ui.input_slider(id, label + " Number", 0, 100, 20)
numbers = ["n1", "n2", "n3", "n4", "n5"]
labels = ["First", "Second", "Third", "Fourth", "Fifth"]
app_ui = ui.page_fluid(
[my_slider(x, y) for x, y in zip(numbers, labels)]
)
app = App(app_ui, None)
IDs need to be unique
This will work once, not more.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
from shiny import App, ui
from shiny import App, render, ui
def io_row():
return ui.layout_columns(
ui.card(ui.input_text("text_input", "Enter text")),
ui.card(ui.output_text("text_output")),
)
app_ui = ui.page_fluid(
io_row(),
)
def server(input, output, session):
@render.text
def text_output():
return f'You entered "{input.text_input()}"'
app = App(app_ui, server)
Modules are functions
- Functions that reads reactive input
- Not to be confused with passing a reactive value into a function
Shiny module
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: horizontal
#| viewerHeight: 500
from shiny import App, module, render, ui
@module.ui
def row_ui():
return ui.layout_columns(
ui.card(ui.input_text("text_in", "Enter text")),
ui.card(ui.output_text("text_out")),
)
@module.server
def row_server(input, output, session):
@output
@render.text
def text_out():
return f'You entered "{input.text_in()}"'
extra_ids = ["row_3", "row_4", "row_5"]
app_ui = ui.page_fluid(row_ui("row_1"), row_ui("row_2"), [row_ui(x) for x in extra_ids])
def server(input, output, session):
row_server("row_1")
row_server("row_2")
[row_server(x) for x in extra_ids]
app = App(app_ui, server)