Search code examples
javascriptrshinyfluent

Update selected item in navigation bar after route_link in R Shiny app built with shiny.fluent and shiny.router


I am facing the following issue in a R Shiny App built with shiny.fluent and shiny.router R packages.

On "home page", I have a href = route_link([...]) link to "test page". The link works, it brings me to the desired "test page". However, the left vertical navigation bar is not updated (it is still "Home" that is identified as the selected item with a different background color).

Does anybody have an idea of what is going on ?

I spent some hours trying to fix it, but nothing so far has worked... I guess that with some javascript the problem could be easily solved, but my knowledge of js is really poor...

Any suggestion (js or not) to solve the issue is welcome !!!

Below minimal code :

library(dplyr)
library(glue)
library(shiny)
library(shiny.fluent)
library(shiny.router)

makeCard <- function(title, content, size = 12, style = "") {
  div(class = glue("card ms-depth-8 ms-sm{size} ms-xl{size}"),
      style = style,
      Stack(
        tokens = list(childrenGap = 5),
        Text(variant = "large", title, block = TRUE),
        content
      ))
}
makePage <- function (title, subtitle, contents) {
  tagList(div(
    class = "page-title",
    span(title, class = "ms-fontSize-32 ms-fontWeight-semibold", style =
           "color: #323130"),
    span(subtitle, class = "ms-fontSize-14 ms-fontWeight-regular", style =
           "color: #605E5C; margin: 14px;")
  ),
  contents)
}
navigation <- "navigation"

navigation <- Nav(
  groups = list(
    list(links = list(
      list(name = 'Home', url = '#!/', key = 'home', icon = 'Home'),
      list(name = 'Test', url = '#!/test', key = 'test', icon = 'AnalyticsReport')
      ))
  ),
  initialSelectedKey = 'home',
  styles = list(
    root = list(
      height = '100%',
      boxSizing = 'border-box',
      overflowY = 'auto'
    )
  )
)
layout <- function(mainUI){
  div(class = "grid-container",
      div(class = "sidenav", navigation),
      div(class = "main", mainUI)
  )
}

home_page <- makePage(
  "This is a Fluent UI app built in Shiny",
  "shiny.react + Fluent UI = shiny.fluent",
  uiOutput(paste0("changepage"))
)
test_page <- makePage(
  "This is a Fluent UI app built in Shiny",
  "shiny.react + Fluent UI = shiny.fluent",
  div(
    makeCard(
      "shiny.react makes it easy to use React libraries in Shiny apps.",
      div(
        Text("my test")
      ))
  )
)

router <- make_router(
  route("/", home_page),
  route("test", test_page))

# Add shiny.router dependencies manually: they are not picked up because they're added in a non-standard way.
shiny::addResourcePath("shiny.router", system.file("www", package = "shiny.router"))
shiny_router_js_src <- file.path("shiny.router", "shiny.router.js")
shiny_router_script_tag <- shiny::tags$script(type = "text/javascript", src = shiny_router_js_src)

ui <- fluentPage(
  layout(router$ui),
  tags$head(
    tags$link(href = "mystyle.css", rel = "stylesheet", type = "text/css"),
    shiny_router_script_tag
  ))

server <- function(input, output, session) {
  router$server(input, output, session)
  output$changepage <- renderUI({
    list(
      tags$ul(
### <<<< WHEN CLICKING ON THIS LINK, NAV BAR SELECTED ITEM IS NOT UPDATED <<<<<<<<<<<<<<<
        tags$li(a(href = route_link("test"), "Go to test page"))
      )
    )
  })
}

shinyApp(ui, server)

to display correctly, also needs www/mystyle.css

body {
  background-color: rgba(225, 223, 221, 0.2);
  min-height: 611px;
  margin: 0;
}
.page-title {
  padding: 52px 0px;
}
.card {
  background: #fff;
  padding: 28px;
  margin-bottom: 28px;
  border-radius: 2px;
  background-clip: padding-box;
}
.grid-container {
  display: grid;
  grid-template-columns: 320px 1fr;
  grid-template-rows: 54px 1fr 45px;
  grid-template-areas: "header header" "sidenav main" "footer footer";
  height: 100vh;
}
.main {
  grid-area: main;
  background-color: #faf9f8;
  padding-left: 40px;
  padding-right: 32px;
  max-width: calc(100vw - 400px);
  max-height: calc(100vh - 100px);
  overflow: auto;
}
.sidenav {
  grid-area: sidenav;
  background-color: #fff;
  padding: 25px;
}

Solution

  • Hi @mazu.

    The expected behavior you described is not a responsibility of shiny.router::route_link function, it only changes the page, any side effects in UI need to be implemented on your own.

    Please see this discussion how it can be implemented on server side using existing features of shiny.router and shiny.fluent.