module.ui

module.ui(fn)

Decorator for defining a Shiny module UI function.

This decorator allows you to write the UI portion of a Shiny module. When your decorated ui function is called with an id, the UI elements defined within will automatically be namespaced using that id. This enables reuse of UI components and consistent input/output handling when paired with a shiny.module.server function.

Parameters

fn : Callable[P, R]

A function that returns a Shiny UI element or layout (e.g., a ui.panel_* component). This function should not accept an id parameter itself; the decorator injects it.

Returns

: Callable[Concatenate[str, P], R]

A function that takes a str id as its first argument, followed by any additional parameters accepted by fn. When called, it returns UI elements with input/output IDs automatically namespaced using the provided module id.

See Also

Examples

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400

## file: app.py
from shiny import App, Inputs, Outputs, Session, module, reactive, render, ui


# ============================================================
# Counter module
# ============================================================
@module.ui
def counter_ui(label: str = "Increment counter") -> ui.TagChild:
    return ui.card(
        ui.h2("This is " + label),
        ui.input_action_button(id="button", label=label),
        ui.output_text(id="out"),
    )


@module.server
def counter_server(
    input: Inputs, output: Outputs, session: Session, starting_value: int = 0
):
    count: reactive.value[int] = reactive.value(starting_value)

    @reactive.effect
    @reactive.event(input.button)
    def _():
        count.set(count() + 1)

    @render.text
    def out() -> str:
        return f"Click count is {count()}"


# =============================================================================
# App that uses module
# =============================================================================
app_ui = ui.page_fluid(
    counter_ui("counter1", "Counter 1"),
    counter_ui("counter2", "Counter 2"),
)


def server(input: Inputs, output: Outputs, session: Session):
    counter_server("counter1")
    counter_server("counter2")


app = App(app_ui, server)