Skip to content

[Bug]: Bookmarking with modules not working #1976

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
SamEdwardes opened this issue Apr 16, 2025 · 4 comments · Fixed by #1983
Closed

[Bug]: Bookmarking with modules not working #1976

SamEdwardes opened this issue Apr 16, 2025 · 4 comments · Fixed by #1983
Assignees
Labels
bug Something isn't working

Comments

@SamEdwardes
Copy link

Component

Other

Severity

P0 - Critical (crash/unusable)

Shiny Version

1.4.0

Python Version

3.13.2

Minimal Reproducible Example

from loguru import logger
from shiny import App, Inputs, Outputs, Session, module, ui
from starlette.requests import Request


# App UI **must** be a function to ensure that each user restores their own UI values.
def app_ui(request: Request):
    return ui.page_fluid(
        ui.markdown(
            "Directions: "
            "\n1. Change the radio button selection below"
            "\n2. Save the bookmark."
            "\n3. Then, refresh your browser page to see the radio button selection has been restored."
        ),
        ui.hr(),
        inputs_ui("inputs_module"),
    )


@module.ui
def inputs_ui():
    return ui.TagList(
        ui.input_radio_buttons("letter", "Choose a letter", choices=["A", "B", "C"]),
        ui.input_bookmark_button(label="Save bookmark!"),
    )


@module.server
def inputs_server(input: Inputs, output: Outputs, session: Session):
    @session.bookmark.on_bookmarked
    async def _on_bookmark(url: str):
        logger.debug("Bookmarking...")
        logger.debug(f"{url=}")
        await session.bookmark.update_query_string(url)
        updated_url = await session.bookmark.get_bookmark_url()
        logger.debug(f"{updated_url=}")
        await session.bookmark.show_bookmark_url_modal()


def server(input: Inputs, output: Outputs, session: Session):
    inputs_server("inputs_module")


app = App(app_ui, server, bookmark_store="url")

Behavior

bookmarks-dont-work.mp4

In contrast, when not using modules, it does work.

bookmark-works.mp4
from loguru import logger
from shiny import App, Inputs, Outputs, Session, ui
from starlette.requests import Request


# App UI **must** be a function to ensure that each user restores their own UI values.
def app_ui(request: Request):
    return ui.page_fluid(
        ui.markdown(
            "Directions: "
            "\n1. Change the radio button selection below"
            "\n2. Save the bookmark."
            "\n3. Then, refresh your browser page to see the radio button selection has been restored."
        ),
        ui.hr(),
        ui.input_radio_buttons("letter", "Choose a letter", choices=["A", "B", "C"]),
        ui.input_bookmark_button(label="Save bookmark!"),
    )


def server(input: Inputs, output: Outputs, session: Session):
    @session.bookmark.on_bookmarked
    async def _on_bookmark(url: str):
        logger.debug("Bookmarking...")
        logger.debug(f"{url=}")
        await session.bookmark.update_query_string(url)
        updated_url = await session.bookmark.get_bookmark_url()
        logger.debug(f"{updated_url=}")
        await session.bookmark.show_bookmark_url_modal()


app = App(app_ui, server, bookmark_store="url")

Error Messages (if any)

No error messages

Environment

anyio==4.9.0
appdirs==1.4.4
asgiref==3.8.1
click==8.1.8
h11==0.14.0
htmltools==0.6.0
idna==3.10
linkify-it-py==2.0.3
loguru==0.7.3
markdown-it-py==3.0.0
mdit-py-plugins==0.4.2
mdurl==0.1.2
narwhals==1.35.0
orjson==3.10.16
packaging==24.2
prompt-toolkit==3.0.51
python-multipart==0.0.20
questionary==2.1.0
setuptools==78.1.0
shiny==1.4.0
sniffio==1.3.1
starlette==0.46.2
typing-extensions==4.13.2
uc-micro-py==1.0.3
uvicorn==0.34.1
watchfiles==1.0.5
wcwidth==0.2.13
websockets==15.0.1
@SamEdwardes SamEdwardes added the bug Something isn't working label Apr 16, 2025
@schloerke schloerke self-assigned this Apr 28, 2025
@SamEdwardes
Copy link
Author

@schloerke thank you for taking a look. Just to clarify - the problem could be I did not set up bookmarks correct for using in modules. In that case adding some documentation about using bookmarks in modules would be helpful :)

The other possible scenarios are:

  • Bookmarking is not supported when using modules.
  • I did set things up correctly, there is a bug.
  • Something else I have not thought of 🤷

@schloerke
Copy link
Collaborator

I found it after a sleep. Which means the current approach is not working.


  • Bookmarking is not automatically supported when using modules.

... Is the correct answer. This behavior is in both R Shiny and py-shiny.

I'll update the docs and tag you as a reviewer.

@SamEdwardes
Copy link
Author

Awesome thank you :)

@SamEdwardes
Copy link
Author

For reference, here is an example that works with modules and bookmarks:

from loguru import logger
from shiny import App, Inputs, Outputs, Session, module, ui, reactive
from starlette.requests import Request


# App UI **must** be a function to ensure that each user restores their own UI values.
def app_ui(request: Request):
    return ui.page_fluid(
        ui.markdown(
            "Directions: "
            "\n1. Change the radio button selection below"
            "\n2. Save the bookmark."
            "\n3. Then, refresh your browser page to see the radio button selection has been restored."
        ),
        ui.hr(),
        inputs_ui("inputs_module"),
    )


@module.ui
def inputs_ui():
    return ui.TagList(
        ui.input_radio_buttons("letter", "Choose a letter", choices=["A", "B", "C"]),
        ui.input_bookmark_button(id="inputs_module_bookmark", label="Save bookmark!"),
    )


@module.server
def inputs_server(input: Inputs, output: Outputs, session: Session):
    session.bookmark.exclude.append("inputs_module_bookmark")

    @reactive.effect
    @reactive.event(input.inputs_module_bookmark)
    async def _do_bookmark():
        logger.debug("Bookmarking state...")
        await session.bookmark()

    @session.bookmark.on_bookmarked
    async def _on_bookmark(url: str):
        logger.debug("Updating URL...")
        logger.debug(f"{url=}")
        await session.bookmark.update_query_string(url)
        updated_url = await session.bookmark.get_bookmark_url()
        logger.debug(f"{updated_url=}")
        await session.bookmark.show_bookmark_url_modal()


def server(input: Inputs, output: Outputs, session: Session):
    inputs_server("inputs_module")


app = App(app_ui, server, bookmark_store="url")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants