module.ui

module.ui(fn)

Decorator for defining a Shiny module UI function.

A Shiny module is a reusable component that can be embedded within Shiny apps or other Shiny modules. Each module consists of a UI function and a server function. Use this decorator to mark the UI function for a module.

The UI function can take whatever parameters are required to create the UI; for example, a label or a default value. It can also take no parameters, if none are required.

Whatever parameters the UI function takes, the ui decorator will prepend the signature with a new id argument. This argument will be an id string passed by the caller, that uniquely identifies the module instance within the calling scope.

When the decorated function is called, any Shiny input or output elements created within the function will automatically have their id values prefixed with the module instance's id. This ensures that the input and output elements are uniquely namespaced and won't conflict with other elements in the same app.

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]

The decorated UI function. The function 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)