Skip to content

Commit

Permalink
Ability to change route from the server.
Browse files Browse the repository at this point in the history
  • Loading branch information
filipstachura committed Nov 28, 2024
1 parent 8ea46df commit 3247851
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 53 deletions.
8 changes: 7 additions & 1 deletion examples/python/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def page(title, content):
# Both sample pages.
root_page = page("Home page", "Welcome on sample routing page!")
other_page = page("Some other page", "Lorem ipsum dolor sit amet.")
third_page = tags.div(menu, tags.h3("Third Page"))
third_page = tags.div(menu, tags.h3("Third Page"), ui.input_action_button(id = "click", label = "Click me"))

# Make output for our router in main UI of Shiny app.
app_ui = ui.page_fluid(
Expand All @@ -46,5 +46,11 @@ def param():
ui.p("No id" if not id else str(id)),
)

@reactive.effect
async def redirect():
input.click()
print("Elo")
await session.send_custom_message("_shiny_router_change_url", {"url": "elo"})


app = App(app_ui, server)
4 changes: 4 additions & 0 deletions inst/www/shiny.router.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@
.router-hidden * {
visibility: inherit;
}

div.router-hidden:where(.shiny-html-output):has(>*) {
display: inherit;
}
10 changes: 9 additions & 1 deletion inst/www/shiny.router.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ window.shinyrouter = function() {
};
}();

var switchUI = function(message) {
const switchUI = function(message) {
// In Shiny for R message can be string and path is send as string.
// In Shiny for Python meesage has to be an object. Path is send as field.
const path = typeof message === "string" ? message : message?.path;
Expand All @@ -56,6 +56,14 @@ var switchUI = function(message) {

Shiny.addCustomMessageHandler("switch-ui", switchUI);

const change_url = function(message) {
// In Shiny for Python meesage has to be an object. Path is send as field.
const url = message.url;
window.location.hash = url;
}

Shiny.addCustomMessageHandler("_shiny_router_change_url", change_url);

$(window).on("hashchange", function (e) {
Shiny.setInputValue("_clientdata_url_hash", window.location.hash);
return;
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
[project]
name = "shiny_router"
version = "0.1.5"
version = "0.1.12"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"pandas",
"shiny",
"shiny-router",
"pytest",
]

[tool.setuptools]
Expand Down
11 changes: 3 additions & 8 deletions src/shiny_router/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,12 @@ def router_callback(input, output, session=None, **kwargs):
@reactive.event(input._clientdata_url_hash)
def _():
requested_path = input._clientdata_url_hash()
log_msg("requested path" + requested_path)
parsed_url = urlparse(requested_path)
fragment_path = urlparse(parsed_url.fragment)
clean_path = fragment_path.path.lstrip("!").lstrip("/")
if clean_path == "":
clean_path = root
query_params = parse_qs(fragment_path.query)

print("Path:", clean_path)
Expand Down Expand Up @@ -112,14 +115,6 @@ def route(path, ui, server=None):
print("Warning: 'server' argument in 'route' is deprecated.")
return {"path": path, "logic": callback_mapping(path, ui, server)}

def router_ui(default, *args, page_404=None):
routes = {**default, **{arg: callback_mapping(arg, ui) for arg, ui in args}}
root = list(default.keys())[0]
if '404' not in routes:
routes['404'] = route('404', page_404)
return {'root': root, 'routes': routes}


def router_ui_internal(router):
# Define paths to JavaScript and CSS files
js_file = "shiny.router.js"
Expand Down
6 changes: 6 additions & 0 deletions tests/python/test_router.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from shiny_router import route_link

def test_route_link():
assert route_link("/") == "./#!/"
assert route_link("abc") == "./#!/abc"
assert route_link("#/xyzq") == "./#!/xyzq"
Loading

0 comments on commit 3247851

Please sign in to comment.